python3izing scripts
This commit is contained in:
@@ -1,41 +1,79 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os,sys
|
import os, sys
|
||||||
import math,shutil,re
|
import math, shutil, re
|
||||||
from random import shuffle
|
from random import shuffle
|
||||||
|
|
||||||
VERSION="0.1"
|
VERSION = "0.1"
|
||||||
|
|
||||||
|
|
||||||
def setup_options():
|
def setup_options():
|
||||||
''' Setup the command line options '''
|
""" Setup the command line options """
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
parser=ArgumentParser(description="Splits files to subfolders equally.")
|
parser = ArgumentParser(description="Splits files to subfolders equally.")
|
||||||
|
|
||||||
parser.add_argument("--order",'-o',type=str,action='store', dest='order',default="sequence",
|
parser.add_argument(
|
||||||
help="Splitting method.",
|
"--order",
|
||||||
choices=['sequence','sparse','regexp','random'])
|
"-o",
|
||||||
parser.add_argument("-m",action='store_true', dest='move',default=False,
|
type=str,
|
||||||
help="Move entries instead of hardlink.")
|
action="store",
|
||||||
parser.add_argument("-f",action='store_true', dest='files',default=False,
|
dest="order",
|
||||||
help="Split files only, skipping folders")
|
default="sequence",
|
||||||
parser.add_argument("-r",'--regexp',type=str,action='store', dest='regexp',default="",
|
help="Splitting method.",
|
||||||
help="Regular expression for splitting. When set, order regexp used, -n not used.")
|
choices=["sequence", "sparse", "regexp", "random"],
|
||||||
parser.add_argument("-n",'-N',type=int,action='store', dest='n',
|
)
|
||||||
help="Number of subfolders to split into.")
|
parser.add_argument(
|
||||||
parser.add_argument("path",type=str,action="store",default=".",nargs="?",
|
"-m",
|
||||||
help="Folder to split.")
|
action="store_true",
|
||||||
options=parser.parse_args()
|
dest="move",
|
||||||
if options.n==None and options.regexp=="":
|
default=False,
|
||||||
|
help="Move entries instead of hardlink.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
action="store_true",
|
||||||
|
dest="files",
|
||||||
|
default=False,
|
||||||
|
help="Split files only, skipping folders",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--regexp",
|
||||||
|
type=str,
|
||||||
|
action="store",
|
||||||
|
dest="regexp",
|
||||||
|
default="",
|
||||||
|
help="Regular expression for splitting. When set, order regexp used, -n not used.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-n",
|
||||||
|
"-N",
|
||||||
|
type=int,
|
||||||
|
action="store",
|
||||||
|
dest="n",
|
||||||
|
help="Number of subfolders to split into.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"path",
|
||||||
|
type=str,
|
||||||
|
action="store",
|
||||||
|
default=".",
|
||||||
|
nargs="?",
|
||||||
|
help="Folder to split.",
|
||||||
|
)
|
||||||
|
options = parser.parse_args()
|
||||||
|
if options.n == None and options.regexp == "":
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
parser.error("Either -n or -r must be passed")
|
parser.error("Either -n or -r must be passed")
|
||||||
if options.regexp!="":
|
if options.regexp != "":
|
||||||
options.order="regexp"
|
options.order = "regexp"
|
||||||
return options
|
return options
|
||||||
|
|
||||||
|
|
||||||
def linktree(src, dst):
|
def linktree(src, dst):
|
||||||
"""Recursively link a directory tree using os.link.
|
"""Recursively link a directory tree using os.link.
|
||||||
Modified from shutil.copytree
|
Modified from shutil.copytree
|
||||||
"""
|
"""
|
||||||
names = os.listdir(src)
|
names = os.listdir(src)
|
||||||
os.makedirs(dst)
|
os.makedirs(dst)
|
||||||
@@ -49,116 +87,124 @@ def linktree(src, dst):
|
|||||||
else:
|
else:
|
||||||
# Will raise a SpecialFileError for unsupported file types
|
# Will raise a SpecialFileError for unsupported file types
|
||||||
os.link(srcname, dstname)
|
os.link(srcname, dstname)
|
||||||
except Error, err:
|
except Error as err:
|
||||||
errors.extend(err.args[0])
|
errors.extend(err.args[0])
|
||||||
except EnvironmentError, why:
|
except EnvironmentError as why:
|
||||||
errors.append((srcname, dstname, str(why)))
|
errors.append((srcname, dstname, str(why)))
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
raise Error, errors
|
raise Error(errors)
|
||||||
|
|
||||||
def copyfileorfolder(basename,source,target,move):
|
|
||||||
''' Copies a file or folder structure under target folder '''
|
def copyfileorfolder(basename, source, target, move):
|
||||||
|
""" Copies a file or folder structure under target folder """
|
||||||
if move:
|
if move:
|
||||||
shutil.move(os.path.join(source,basename),os.path.join(target,basename))
|
shutil.move(os.path.join(source, basename), os.path.join(target, basename))
|
||||||
return
|
return
|
||||||
if os.path.isfile(os.path.join(source,basename)):
|
if os.path.isfile(os.path.join(source, basename)):
|
||||||
os.link(os.path.join(source,basename),os.path.join(target,basename))
|
os.link(os.path.join(source, basename), os.path.join(target, basename))
|
||||||
return
|
return
|
||||||
if os.path.isdir(os.path.join(source,basename)):
|
if os.path.isdir(os.path.join(source, basename)):
|
||||||
linktree(os.path.join(source,basename),os.path.join(target,basename))
|
linktree(os.path.join(source, basename), os.path.join(target, basename))
|
||||||
return
|
return
|
||||||
raise RuntimeError(source+' was neither file nor folder.')
|
raise RuntimeError(source + " was neither file nor folder.")
|
||||||
|
|
||||||
def portorder(inFiles,inFolder,outFolders,N,link):
|
|
||||||
''' Copy files in port order (sparse) '''
|
def portorder(inFiles, inFolder, outFolders, N, link):
|
||||||
outidx=0
|
""" Copy files in port order (sparse) """
|
||||||
|
outidx = 0
|
||||||
for row in inFiles:
|
for row in inFiles:
|
||||||
copyfileorfolder(row,inFolder,outFolders[outidx],link)
|
copyfileorfolder(row, inFolder, outFolders[outidx], link)
|
||||||
outidx+=1
|
outidx += 1
|
||||||
if outidx+1>N:
|
if outidx + 1 > N:
|
||||||
outidx=0
|
outidx = 0
|
||||||
|
|
||||||
def fileorder(inFiles,inFolder,outFolders,N,link):
|
|
||||||
''' Copy files in input file order (sequnce) '''
|
|
||||||
|
|
||||||
bins=[int(math.floor(float(len(inFiles))/float(N)))]*int(N)
|
def fileorder(inFiles, inFolder, outFolders, N, link):
|
||||||
binidx=0
|
""" Copy files in input file order (sequnce) """
|
||||||
while sum(bins)<len(inFiles):
|
|
||||||
bins[binidx]+=1
|
bins = [int(math.floor(float(len(inFiles)) / float(N)))] * int(N)
|
||||||
binidx+=1
|
binidx = 0
|
||||||
offsets=list(offset(bins))
|
while sum(bins) < len(inFiles):
|
||||||
offsets.insert(0,0)
|
bins[binidx] += 1
|
||||||
|
binidx += 1
|
||||||
|
offsets = list(offset(bins))
|
||||||
|
offsets.insert(0, 0)
|
||||||
|
|
||||||
for outidx in range(N):
|
for outidx in range(N):
|
||||||
for f in range(offsets[outidx], offsets[outidx]+bins[outidx]):
|
for f in range(offsets[outidx], offsets[outidx] + bins[outidx]):
|
||||||
copyfileorfolder(inFiles[f],inFolder,outFolders[outidx],link)
|
copyfileorfolder(inFiles[f], inFolder, outFolders[outidx], link)
|
||||||
|
|
||||||
def regexorder(inFiles,inFolder,outFolders,matcher,uniqlabel,link):
|
|
||||||
''' Copy files by regex match '''
|
def regexorder(inFiles, inFolder, outFolders, matcher, uniqlabel, link):
|
||||||
|
""" Copy files by regex match """
|
||||||
|
|
||||||
for f in inFiles:
|
for f in inFiles:
|
||||||
m=matcher.search(f)
|
m = matcher.search(f)
|
||||||
if m:
|
if m:
|
||||||
outidx=uniqlabel.index(m.group(1))
|
outidx = uniqlabel.index(m.group(1))
|
||||||
copyfileorfolder(f,inFolder,outFolders[outidx],link)
|
copyfileorfolder(f, inFolder, outFolders[outidx], link)
|
||||||
|
|
||||||
|
|
||||||
def regexmatches(inFiles, opts):
|
def regexmatches(inFiles, opts):
|
||||||
matcher=re.compile(opts.regexp)
|
matcher = re.compile(opts.regexp)
|
||||||
matches=[]
|
matches = []
|
||||||
skipped=0
|
skipped = 0
|
||||||
for f in inFiles:
|
for f in inFiles:
|
||||||
m=matcher.search(f)
|
m = matcher.search(f)
|
||||||
if m:
|
if m:
|
||||||
matches.append(m.group(1))
|
matches.append(m.group(1))
|
||||||
else:
|
else:
|
||||||
skipped+=1
|
skipped += 1
|
||||||
uniqlabel=sorted(set(matches))
|
uniqlabel = sorted(set(matches))
|
||||||
print("Unique matches",uniqlabel)
|
print("Unique matches", uniqlabel)
|
||||||
print("Not matching %d files."% skipped)
|
print("Not matching %d files." % skipped)
|
||||||
for x in uniqlabel:
|
for x in uniqlabel:
|
||||||
outFolders.append(os.path.join(opts.path,x))
|
outFolders.append(os.path.join(opts.path, x))
|
||||||
return (outFolders, uniqlabel, matcher)
|
return (outFolders, uniqlabel, matcher)
|
||||||
|
|
||||||
|
|
||||||
def offset(it):
|
def offset(it):
|
||||||
total = 0
|
total = 0
|
||||||
for x in it:
|
for x in it:
|
||||||
total += x
|
total += x
|
||||||
yield total
|
yield total
|
||||||
|
|
||||||
|
|
||||||
def report(outFolders):
|
def report(outFolders):
|
||||||
for x in outFolders:
|
for x in outFolders:
|
||||||
n=len(os.listdir(x))
|
n = len(os.listdir(x))
|
||||||
print( os.path.basename( x )+":"+str(n) )
|
print(os.path.basename(x) + ":" + str(n))
|
||||||
|
|
||||||
''' Splits a folder input in N outputs '''
|
|
||||||
options=setup_options()
|
""" Splits a folder input in N outputs """
|
||||||
outFolders=[]
|
options = setup_options()
|
||||||
|
outFolders = []
|
||||||
method = options.order.lower().strip()
|
method = options.order.lower().strip()
|
||||||
# list files, and remove hidden (.files)
|
# list files, and remove hidden (.files)
|
||||||
inFiles=sorted(filter(lambda x: not x.startswith('.'), os.listdir(options.path)))
|
inFiles = sorted(filter(lambda x: not x.startswith("."), os.listdir(options.path)))
|
||||||
if options.files:
|
if options.files:
|
||||||
inFiles=[ f for f in inFiles if os.path.isfile( os.path.join( options.path, f ) ) ]
|
inFiles = [f for f in inFiles if os.path.isfile(os.path.join(options.path, f))]
|
||||||
|
|
||||||
if method=='regexp':
|
if method == "regexp":
|
||||||
(outFolders, uniqlabel, matcher)=regexmatches(inFiles, options)
|
(outFolders, uniqlabel, matcher) = regexmatches(inFiles, options)
|
||||||
raw_input("correct?")
|
input("correct?")
|
||||||
else:
|
else:
|
||||||
for x in range(options.n):
|
for x in range(options.n):
|
||||||
outFolders.append(os.path.join(options.path,'folder'+str(x+1)))
|
outFolders.append(os.path.join(options.path, "folder" + str(x + 1)))
|
||||||
|
|
||||||
for x in outFolders:
|
for x in outFolders:
|
||||||
if not os.path.isdir(x):
|
if not os.path.isdir(x):
|
||||||
os.mkdir(x)
|
os.mkdir(x)
|
||||||
if method=='random':
|
if method == "random":
|
||||||
shuffle(inFiles)
|
shuffle(inFiles)
|
||||||
portorder(inFiles,options.path,outFolders,options.n,options.move)
|
portorder(inFiles, options.path, outFolders, options.n, options.move)
|
||||||
if method=='regexp':
|
if method == "regexp":
|
||||||
regexorder(inFiles,options.path,outFolders,matcher,uniqlabel,options.move)
|
regexorder(inFiles, options.path, outFolders, matcher, uniqlabel, options.move)
|
||||||
if method=='sparse':
|
if method == "sparse":
|
||||||
portorder(inFiles,options.path,outFolders,options.n,options.move)
|
portorder(inFiles, options.path, outFolders, options.n, options.move)
|
||||||
if method=='sequence':
|
if method == "sequence":
|
||||||
fileorder(inFiles,options.path,outFolders,options.n,options.move)
|
fileorder(inFiles, options.path, outFolders, options.n, options.move)
|
||||||
|
|
||||||
|
|
||||||
report(outFolders)
|
report(outFolders)
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys,re,os
|
import sys, re, os
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from argparse import RawTextHelpFormatter
|
from argparse import RawTextHelpFormatter
|
||||||
|
|
||||||
|
|
||||||
def setup_options():
|
def setup_options():
|
||||||
parser = ArgumentParser(
|
parser = ArgumentParser(
|
||||||
description="""Template Filler
|
description="""Template Filler
|
||||||
@@ -15,33 +16,30 @@ def setup_options():
|
|||||||
[[name]]=John
|
[[name]]=John
|
||||||
[[letter]]=@letter.txt
|
[[letter]]=@letter.txt
|
||||||
""",
|
""",
|
||||||
formatter_class = RawTextHelpFormatter
|
formatter_class=RawTextHelpFormatter,
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-e",
|
"-e",
|
||||||
action = "store_true",
|
action="store_true",
|
||||||
dest = "env",
|
dest="env",
|
||||||
default = False,
|
default=False,
|
||||||
help = "Use the environment to replace ${env} style variables."
|
help="Use the environment to replace ${env} style variables.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-f",
|
"-f", action="store", dest="file", help="File name to read keys/values."
|
||||||
action = "store",
|
|
||||||
dest = "file",
|
|
||||||
help = "File name to read keys/values."
|
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-p",
|
"-p",
|
||||||
action = "append",
|
action="append",
|
||||||
dest = "values",
|
dest="values",
|
||||||
default = [],
|
default=[],
|
||||||
help = "key=value pairs. This option may be issued several times."
|
help="key=value pairs. This option may be issued several times.",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'template',
|
"template",
|
||||||
action = "store",
|
action="store",
|
||||||
nargs = '?',
|
nargs="?",
|
||||||
help = "Template file to be filled. If not defined, stdin used."
|
help="Template file to be filled. If not defined, stdin used.",
|
||||||
)
|
)
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
return options
|
return options
|
||||||
@@ -54,28 +52,34 @@ def parse_file(filename):
|
|||||||
l = l.rstrip("\n\r")
|
l = l.rstrip("\n\r")
|
||||||
if len(l) == 0:
|
if len(l) == 0:
|
||||||
continue
|
continue
|
||||||
tokens = l.split('=', 1)
|
tokens = l.split("=", 1)
|
||||||
if len(tokens) != 2:
|
if len(tokens) != 2:
|
||||||
print("File %s:%i key=value pair '%s' does not parse"%(
|
print(
|
||||||
filename, i+1, l,
|
"File %s:%i key=value pair '%s' does not parse"
|
||||||
))
|
% (
|
||||||
|
filename,
|
||||||
|
i + 1,
|
||||||
|
l,
|
||||||
|
)
|
||||||
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
pairs.append( (tokens[0], tokens[1]) )
|
pairs.append((tokens[0], tokens[1]))
|
||||||
return pairs
|
return pairs
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments(args):
|
def parse_arguments(args):
|
||||||
pairs = []
|
pairs = []
|
||||||
for p in args:
|
for p in args:
|
||||||
tokens = p.split('=', 1)
|
tokens = p.split("=", 1)
|
||||||
if len(tokens) != 2:
|
if len(tokens) != 2:
|
||||||
print("Argument key=value pair '%s' does not parse"%(p,))
|
print("Argument key=value pair '%s' does not parse" % (p,))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
pairs.append( (tokens[0], tokens[1]) )
|
pairs.append((tokens[0], tokens[1]))
|
||||||
return pairs
|
return pairs
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
options = setup_options();
|
options = setup_options()
|
||||||
pairs = []
|
pairs = []
|
||||||
if options.file != None:
|
if options.file != None:
|
||||||
pairs.extend(parse_file(options.file))
|
pairs.extend(parse_file(options.file))
|
||||||
@@ -83,18 +87,18 @@ if __name__ == "__main__":
|
|||||||
if options.template == None:
|
if options.template == None:
|
||||||
in_reader = sys.stdin
|
in_reader = sys.stdin
|
||||||
else:
|
else:
|
||||||
in_reader = open(options.template, 'rb')
|
in_reader = open(options.template, "rb")
|
||||||
for l in in_reader:
|
for l in in_reader:
|
||||||
for p in pairs:
|
for p in pairs:
|
||||||
value = p[1]
|
value = p[1]
|
||||||
if len(value) > 0:
|
if len(value) > 0:
|
||||||
if value[0] == "@":
|
if value[0] == "@":
|
||||||
value = open(value[1:], 'rt').read()
|
value = open(value[1:], "rt").read()
|
||||||
elif value[0:2] == "\\@":
|
elif value[0:2] == "\\@":
|
||||||
value = value[1:]
|
value = value[1:]
|
||||||
l = l.replace(p[0].encode('utf-8'), value.encode('utf-8'))
|
l = l.replace(p[0].encode("utf-8"), value.encode("utf-8"))
|
||||||
if options.env:
|
if options.env:
|
||||||
var_list = [m.group(0) for m in re.finditer('\${[^ ]+}', l)]
|
var_list = [m.group(0) for m in re.finditer("\${[^ ]+}", l)]
|
||||||
for v in var_list:
|
for v in var_list:
|
||||||
l = l.replace(v, os.environ.get(v[:-1][2:], ""))
|
l = l.replace(v, os.environ.get(v[:-1][2:], ""))
|
||||||
sys.stdout.write(l.decode('utf-8'))
|
sys.stdout.write(l.decode("utf-8"))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
@@ -10,57 +10,125 @@ import time
|
|||||||
import tty
|
import tty
|
||||||
|
|
||||||
|
|
||||||
readline.parse_and_bind('tab: complete')
|
readline.parse_and_bind("tab: complete")
|
||||||
readline.parse_and_bind('set editing-mode vi')
|
readline.parse_and_bind("set editing-mode vi")
|
||||||
|
|
||||||
MENUFILE = '.foldermenu'
|
MENUFILE = ".foldermenu"
|
||||||
DEFAULTFILE = os.path.expanduser(os.path.join('~','.config','foldermenu','default'))
|
DEFAULTFILE = os.path.expanduser(os.path.join("~", ".config", "foldermenu", "default"))
|
||||||
VERSION = "0.5"
|
VERSION = "0.5"
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
|
|
||||||
def setup_options():
|
def setup_options():
|
||||||
''' Setup the command line options '''
|
""" Setup the command line options """
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
parser=ArgumentParser(description="Prints folder specific shell commands stored in '" + MENUFILE +
|
parser = ArgumentParser(
|
||||||
"' file, and in addition the executables in the current folder. " +
|
description="Prints folder specific shell commands stored in '"
|
||||||
"Menufile format for each line: 'description:command'. " +
|
+ MENUFILE
|
||||||
"If the command ends in '&' it is run in the background. " +
|
+ "' file, and in addition the executables in the current folder. "
|
||||||
"If the command ends in '/' it is a folder, and selecting will enter. " +
|
+ "Menufile format for each line: 'description:command'. "
|
||||||
"Extra keyboard shortcuts: / Edit, $ Shell ")
|
+ "If the command ends in '&' it is run in the background. "
|
||||||
parser.add_argument("-1","--one-shot",action = 'store_true', dest = 'once', default = False,
|
+ "If the command ends in '/' it is a folder, and selecting will enter. "
|
||||||
help = "Launch only once, then exit")
|
+ "Extra keyboard shortcuts: / Edit, $ Shell "
|
||||||
parser.add_argument("-b","--no-banner", action='store_false', dest='banner', default=True,
|
)
|
||||||
help="Do not show banners. Banners are ## starting lines in the file")
|
parser.add_argument(
|
||||||
parser.add_argument("-d","--no-defaults",action='store_false', dest='defaults',default=True,
|
"-1",
|
||||||
help="Do not show default entries from "+DEFAULTFILE)
|
"--one-shot",
|
||||||
parser.add_argument("-x","--no-exec",action='store_false', dest='executables',default=True,
|
action="store_true",
|
||||||
help="Do not show executables in the listing.")
|
dest="once",
|
||||||
parser.add_argument("--columns",'-f','-C',type=int,action='store', dest='columns',default=0,
|
default=False,
|
||||||
help="Number of columns. 0 for automatic")
|
help="Launch only once, then exit",
|
||||||
parser.add_argument("-l","--list",action='store_true', dest='list',default=False,
|
)
|
||||||
help="Print the list, don't wait for keypress.")
|
parser.add_argument(
|
||||||
parser.add_argument("--command",'-c',type=str,action='store', dest='command',
|
"-b",
|
||||||
help="Command to run (1-9a-z..), any argumets after -- are forwarded to the command ")
|
"--no-banner",
|
||||||
parser.add_argument("--no-colors",'--nc',action="store_false",dest="colors",default=True,
|
action="store_false",
|
||||||
help="Disable colored output")
|
dest="banner",
|
||||||
parser.add_argument("--horizontal",'-H',action="store_true",dest="horizontal",default=False,
|
default=True,
|
||||||
help="Horizontal order of items, only valid for -l listing.")
|
help="Do not show banners. Banners are ## starting lines in the file",
|
||||||
parser.add_argument("--version",action='version', version=VERSION)
|
)
|
||||||
parser.add_argument("args",type=str,action="store",default="",nargs="?",
|
parser.add_argument(
|
||||||
help="Arguments for the command, if -c used. The string will be re-parsed with shutils. Use '--' to skip local parsing.")
|
"-d",
|
||||||
|
"--no-defaults",
|
||||||
|
action="store_false",
|
||||||
|
dest="defaults",
|
||||||
|
default=True,
|
||||||
|
help="Do not show default entries from " + DEFAULTFILE,
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-x",
|
||||||
|
"--no-exec",
|
||||||
|
action="store_false",
|
||||||
|
dest="executables",
|
||||||
|
default=True,
|
||||||
|
help="Do not show executables in the listing.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--columns",
|
||||||
|
"-f",
|
||||||
|
"-C",
|
||||||
|
type=int,
|
||||||
|
action="store",
|
||||||
|
dest="columns",
|
||||||
|
default=0,
|
||||||
|
help="Number of columns. 0 for automatic",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l",
|
||||||
|
"--list",
|
||||||
|
action="store_true",
|
||||||
|
dest="list",
|
||||||
|
default=False,
|
||||||
|
help="Print the list, don't wait for keypress.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--command",
|
||||||
|
"-c",
|
||||||
|
type=str,
|
||||||
|
action="store",
|
||||||
|
dest="command",
|
||||||
|
help="Command to run (1-9a-z..), any argumets after -- are forwarded to the command ",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--no-colors",
|
||||||
|
"--nc",
|
||||||
|
action="store_false",
|
||||||
|
dest="colors",
|
||||||
|
default=True,
|
||||||
|
help="Disable colored output",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--horizontal",
|
||||||
|
"-H",
|
||||||
|
action="store_true",
|
||||||
|
dest="horizontal",
|
||||||
|
default=False,
|
||||||
|
help="Horizontal order of items, only valid for -l listing.",
|
||||||
|
)
|
||||||
|
parser.add_argument("--version", action="version", version=VERSION)
|
||||||
|
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.",
|
||||||
|
)
|
||||||
|
|
||||||
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)
|
||||||
@@ -73,36 +141,37 @@ def ichr(i):
|
|||||||
i += 64 - 122
|
i += 64 - 122
|
||||||
return chr(i)
|
return chr(i)
|
||||||
|
|
||||||
|
|
||||||
class bc:
|
class bc:
|
||||||
MAG = '\033[35m'
|
MAG = "\033[35m"
|
||||||
BLU = '\033[34m'
|
BLU = "\033[34m"
|
||||||
GRE = '\033[32m'
|
GRE = "\033[32m"
|
||||||
YEL = '\033[33m'
|
YEL = "\033[33m"
|
||||||
RED = '\033[31m'
|
RED = "\033[31m"
|
||||||
CYA = '\033[36m'
|
CYA = "\033[36m"
|
||||||
WHI = '\033[1m'
|
WHI = "\033[1m"
|
||||||
BG_BLK = '\033[40m'
|
BG_BLK = "\033[40m"
|
||||||
END = '\033[0m'
|
END = "\033[0m"
|
||||||
CLR = '\033[2J'
|
CLR = "\033[2J"
|
||||||
INV = '\033[7m'
|
INV = "\033[7m"
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
self.MAG = ''
|
self.MAG = ""
|
||||||
self.BLU = ''
|
self.BLU = ""
|
||||||
self.GRE = ''
|
self.GRE = ""
|
||||||
self.YEL = ''
|
self.YEL = ""
|
||||||
self.RED = ''
|
self.RED = ""
|
||||||
self.CYA = ''
|
self.CYA = ""
|
||||||
self.WHI = ''
|
self.WHI = ""
|
||||||
self.END = ''
|
self.END = ""
|
||||||
self.BG_BLK = ''
|
self.BG_BLK = ""
|
||||||
self.INV = ''
|
self.INV = ""
|
||||||
|
|
||||||
def pos(self,y,x):
|
def pos(self, y, x):
|
||||||
return "\033[%s;%sH"%( y, x )
|
return "\033[%s;%sH" % (y, x)
|
||||||
|
|
||||||
def posprint(self, y, x, s):
|
def posprint(self, y, x, s):
|
||||||
sys.stdout.write( self.pos(y, x) + str(s) )
|
sys.stdout.write(self.pos(y, x) + str(s))
|
||||||
|
|
||||||
|
|
||||||
class getch:
|
class getch:
|
||||||
@@ -122,18 +191,21 @@ class getch:
|
|||||||
|
|
||||||
|
|
||||||
class launch_item:
|
class launch_item:
|
||||||
''' Class for launchable items '''
|
""" Class for launchable items """
|
||||||
|
|
||||||
def __init__(self, command, description, launcher):
|
def __init__(self, command, description, launcher):
|
||||||
self.command = command
|
self.command = command
|
||||||
self.description = description
|
self.description = description
|
||||||
self.launcher = launcher
|
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 """
|
||||||
|
|
||||||
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.menu_keys = [ichr(i + 1) for i in range(60)]
|
||||||
self.args = ''
|
self.args = ""
|
||||||
self.co = bc()
|
self.co = bc()
|
||||||
self.dir_mode = False
|
self.dir_mode = False
|
||||||
self.max_length = 0
|
self.max_length = 0
|
||||||
@@ -160,76 +232,58 @@ class entry_collection:
|
|||||||
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):
|
||||||
with open(menu_file, 'rt') as f:
|
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(
|
self.banner.append(row[2:].replace("\n", "").replace("\r", ""))
|
||||||
row[2:].replace("\n","").replace("\r","")
|
|
||||||
)
|
|
||||||
continue
|
continue
|
||||||
if row[0] == '#':
|
if row[0] == "#":
|
||||||
continue
|
continue
|
||||||
row = row.strip().split(':',1)
|
row = row.strip().split(":", 1)
|
||||||
if len(row) == 1:
|
if len(row) == 1:
|
||||||
row = [ row[0].strip(), row[0] ]
|
row = [row[0].strip(), row[0]]
|
||||||
else:
|
else:
|
||||||
row = [ row[0].strip(), row[1] ]
|
row = [row[0].strip(), row[1]]
|
||||||
if len(row[1]) == 0:
|
if len(row[1]) == 0:
|
||||||
row[1] = " "
|
row[1] = " "
|
||||||
launcher = "menu"
|
launcher = "menu"
|
||||||
if row[1][-1] == '/' and os.path.isdir(row[1]):
|
if row[1][-1] == "/" and os.path.isdir(row[1]):
|
||||||
launcher = "dir"
|
launcher = "dir"
|
||||||
if row[0][-1] != "/":
|
if row[0][-1] != "/":
|
||||||
row[0] += "/"
|
row[0] += "/"
|
||||||
self.entries.append(
|
self.entries.append(
|
||||||
launch_item(
|
launch_item(
|
||||||
command = row[1],
|
command=row[1], description=row[0], launcher=launcher
|
||||||
description = row[0],
|
|
||||||
launcher = launcher
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
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(
|
self.dirs.append(launch_item(command="..", description="..", launcher="dir"))
|
||||||
launch_item(
|
|
||||||
command = '..',
|
|
||||||
description = '..',
|
|
||||||
launcher = "dir"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dirs = []
|
dirs = []
|
||||||
executables = []
|
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(
|
self.dirs.append(
|
||||||
launch_item(
|
launch_item(command=d, description=d + "/", launcher="dir")
|
||||||
command = d,
|
|
||||||
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(
|
self.entries.append(
|
||||||
launch_item(
|
launch_item(command=e, description=e, launcher="exec")
|
||||||
command = e,
|
|
||||||
description = e,
|
|
||||||
launcher = "exec"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def entry_color(self, launcher):
|
def entry_color(self, launcher):
|
||||||
@@ -246,11 +300,11 @@ class entry_collection:
|
|||||||
helptext = "[.]commands"
|
helptext = "[.]commands"
|
||||||
my_entries = self.dirs
|
my_entries = self.dirs
|
||||||
else:
|
else:
|
||||||
helptext = '[.]folders [-]args %s(%s%s%s)'%(
|
helptext = "[.]folders [-]args %s(%s%s%s)" % (
|
||||||
self.co.END + self.co.MAG,
|
self.co.END + self.co.MAG,
|
||||||
self.co.END,
|
self.co.END,
|
||||||
self.args,
|
self.args,
|
||||||
self.co.MAG
|
self.co.MAG,
|
||||||
)
|
)
|
||||||
my_entries = self.entries
|
my_entries = self.entries
|
||||||
|
|
||||||
@@ -271,34 +325,21 @@ class entry_collection:
|
|||||||
else:
|
else:
|
||||||
banner = []
|
banner = []
|
||||||
blen = len(banner)
|
blen = len(banner)
|
||||||
cwd = os.path.basename( os.getcwd() )[0:15]
|
cwd = os.path.basename(os.getcwd())[0:15]
|
||||||
|
|
||||||
self.co.posprint(
|
self.co.posprint(1, 1, self.co.END + self.co.CLR)
|
||||||
1,
|
|
||||||
1,
|
|
||||||
self.co.END + self.co.CLR
|
|
||||||
)
|
|
||||||
self.co.posprint(
|
self.co.posprint(
|
||||||
1,
|
1,
|
||||||
3,
|
3,
|
||||||
"%s%s%s [q/x]exit %s%s"%(
|
"%s%s%s [q/x]exit %s%s"
|
||||||
self.co.WHI,
|
% (self.co.WHI, cwd, self.co.MAG, helptext, self.co.END),
|
||||||
cwd,
|
|
||||||
self.co.MAG,
|
|
||||||
helptext,
|
|
||||||
self.co.END
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
for i, e in enumerate(banner):
|
for i, e in enumerate(banner):
|
||||||
self.co.posprint(
|
self.co.posprint(i + 2, 0, e)
|
||||||
i+2,
|
rows = int(math.ceil(len(my_entries) / pars))
|
||||||
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
|
||||||
@@ -313,16 +354,17 @@ class entry_collection:
|
|||||||
column = 2
|
column = 2
|
||||||
border = ""
|
border = ""
|
||||||
else:
|
else:
|
||||||
column = maxcolumns * ( par - 1 )
|
column = maxcolumns * (par - 1)
|
||||||
border = '| '
|
border = "| "
|
||||||
if self.selected == index:
|
if self.selected == index:
|
||||||
highlight = self.co.INV + ">"
|
highlight = self.co.INV + ">"
|
||||||
else:
|
else:
|
||||||
highlight = ' '
|
highlight = " "
|
||||||
self.co.posprint(
|
self.co.posprint(
|
||||||
r+1,
|
r + 1,
|
||||||
column,
|
column,
|
||||||
"%s%s%s%s%s%s%s%s"%(
|
"%s%s%s%s%s%s%s%s"
|
||||||
|
% (
|
||||||
border,
|
border,
|
||||||
self.co.WHI,
|
self.co.WHI,
|
||||||
key,
|
key,
|
||||||
@@ -330,16 +372,13 @@ class entry_collection:
|
|||||||
self.entry_color(entry.launcher),
|
self.entry_color(entry.launcher),
|
||||||
highlight,
|
highlight,
|
||||||
printline,
|
printline,
|
||||||
self.co.END
|
self.co.END,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
r += 1
|
r += 1
|
||||||
self.co.posprint(
|
self.co.posprint(rows + 2 + blen, 0, "#")
|
||||||
rows + 2 + blen,
|
|
||||||
0,
|
|
||||||
"#"
|
|
||||||
)
|
|
||||||
self.rows = rows
|
self.rows = rows
|
||||||
|
sys.stdout.flush()
|
||||||
|
|
||||||
def list(self):
|
def list(self):
|
||||||
""" draws the list at cursor """
|
""" draws the list at cursor """
|
||||||
@@ -350,18 +389,13 @@ class entry_collection:
|
|||||||
if self.options.columns == 0:
|
if self.options.columns == 0:
|
||||||
pars = 1.0
|
pars = 1.0
|
||||||
if len(self.entries) > 9:
|
if len(self.entries) > 9:
|
||||||
pars = max(
|
pars = max(1.0, math.floor(maxcolumns / float(self.max_length)))
|
||||||
1.0,
|
|
||||||
math.floor(
|
|
||||||
maxcolumns / float(self.max_length)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
while len(self.entries) / pars < pars:
|
while len(self.entries) / pars < pars:
|
||||||
pars -= 1
|
pars -= 1
|
||||||
else:
|
else:
|
||||||
pars = float(self.options.columns)
|
pars = float(self.options.columns)
|
||||||
|
|
||||||
rows = int(math.ceil( len(self.entries) / float(pars) ))
|
rows = int(math.ceil(len(self.entries) / float(pars)))
|
||||||
maxcolumns = int(math.floor(maxcolumns / pars)) - 2
|
maxcolumns = int(math.floor(maxcolumns / pars)) - 2
|
||||||
# If names won't fit the columns, make sure at least 3 characters are visible
|
# If names won't fit the columns, make sure at least 3 characters are visible
|
||||||
if maxcolumns < 6:
|
if maxcolumns < 6:
|
||||||
@@ -370,8 +404,8 @@ class entry_collection:
|
|||||||
origmaxcolumns -= 10
|
origmaxcolumns -= 10
|
||||||
while maxcolumns < 6:
|
while maxcolumns < 6:
|
||||||
pars -= 1
|
pars -= 1
|
||||||
rows = int(math.ceil( len(self.entries) / float(pars) ))
|
rows = int(math.ceil(len(self.entries) / float(pars)))
|
||||||
maxcolumns = int(math.floor( origmaxcolumns / pars )) - 2
|
maxcolumns = int(math.floor(origmaxcolumns / pars)) - 2
|
||||||
|
|
||||||
self.max_length = min(maxcolumns, self.max_length)
|
self.max_length = min(maxcolumns, self.max_length)
|
||||||
if self.options.horizontal:
|
if self.options.horizontal:
|
||||||
@@ -380,24 +414,24 @@ class entry_collection:
|
|||||||
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 entry,key 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 += 1
|
||||||
r = 0
|
r = 0
|
||||||
printline = entry.description[:(maxcolumns-3)]
|
printline = entry.description[: (maxcolumns - 3)]
|
||||||
printline += ' '*(self.max_length-len(printline)-1)
|
printline += " " * (self.max_length - len(printline) - 1)
|
||||||
formatted[r][par]="%s%s%s %s%s%s"%(
|
formatted[r][par] = "%s%s%s %s%s%s" % (
|
||||||
self.co.WHI,
|
self.co.WHI,
|
||||||
key,
|
key,
|
||||||
self.co.END,
|
self.co.END,
|
||||||
self.entry_color(entry.launcher),
|
self.entry_color(entry.launcher),
|
||||||
printline,
|
printline,
|
||||||
self.co.END
|
self.co.END,
|
||||||
)
|
)
|
||||||
r += 1
|
r += 1
|
||||||
if self.options.horizontal:
|
if self.options.horizontal:
|
||||||
@@ -407,10 +441,10 @@ class entry_collection:
|
|||||||
if self.banner:
|
if self.banner:
|
||||||
print("\n".join(self.banner))
|
print("\n".join(self.banner))
|
||||||
for row in formatted:
|
for row in formatted:
|
||||||
print('|'.join(row))
|
print("|".join(row))
|
||||||
|
|
||||||
def launch(self, key):
|
def launch(self, key):
|
||||||
''' launch the given entry '''
|
""" launch the given entry """
|
||||||
|
|
||||||
bg = False
|
bg = False
|
||||||
idx = self.menu_keys.index(key)
|
idx = self.menu_keys.index(key)
|
||||||
@@ -428,14 +462,14 @@ class entry_collection:
|
|||||||
self.selected = -1
|
self.selected = -1
|
||||||
return
|
return
|
||||||
|
|
||||||
if command_str[-1] == '&':
|
if command_str[-1] == "&":
|
||||||
#Run the program in background
|
# Run the program in background
|
||||||
command_str = command_str[:-1]
|
command_str = command_str[:-1]
|
||||||
bg = True
|
bg = True
|
||||||
if len(self.args) > 0:
|
if len(self.args) > 0:
|
||||||
command_str += ' ' + self.args
|
command_str += " " + self.args
|
||||||
if self.entries[idx].launcher == 'exec':
|
if self.entries[idx].launcher == "exec":
|
||||||
command_str = './' + command_str
|
command_str = "./" + command_str
|
||||||
|
|
||||||
if not self.options.command:
|
if not self.options.command:
|
||||||
print(command_str)
|
print(command_str)
|
||||||
@@ -443,24 +477,24 @@ class entry_collection:
|
|||||||
if bg:
|
if bg:
|
||||||
subprocess.Popen(
|
subprocess.Popen(
|
||||||
command_str,
|
command_str,
|
||||||
stderr = subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
shell=True,
|
shell=True,
|
||||||
executable="/bin/bash"
|
executable="/bin/bash",
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
command_str,
|
command_str,
|
||||||
stderr = subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
shell = True,
|
shell=True,
|
||||||
executable = "/bin/bash"
|
executable="/bin/bash",
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
print('Non-zero exit code: "' + command_str + '"')
|
print('Non-zero exit code: "' + command_str + '"')
|
||||||
|
|
||||||
if not (self.options.command or self.options.once or bg):
|
if not (self.options.command or self.options.once or bg):
|
||||||
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
|
||||||
@@ -474,10 +508,10 @@ class entry_collection:
|
|||||||
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 select_move(self, delta):
|
def select_move(self, delta):
|
||||||
new_value = self.selected + delta
|
new_value = self.selected + delta
|
||||||
@@ -493,30 +527,27 @@ class entry_collection:
|
|||||||
|
|
||||||
def edit_menu(self):
|
def edit_menu(self):
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
"vim %s"%( MENUFILE, ),
|
"vim %s" % (MENUFILE,),
|
||||||
stderr = subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
shell = True,
|
shell=True,
|
||||||
executable = "/bin/bash"
|
executable="/bin/bash",
|
||||||
)
|
)
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|
||||||
def shell(self):
|
def shell(self):
|
||||||
#env = os.environ.copy()
|
# env = os.environ.copy()
|
||||||
#env["PS1"] = "fM:" + env.get("PS1","")
|
# env["PS1"] = "fM:" + env.get("PS1","")
|
||||||
subprocess.call(
|
subprocess.call(
|
||||||
"bash --rcfile <(cat ~/.bashrc; echo \"PS1='folderMenu: '\$PS1\") -i",
|
"bash --rcfile <(cat ~/.bashrc; echo \"PS1='folderMenu: '\$PS1\") -i",
|
||||||
stderr = subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
shell = True,
|
shell=True,
|
||||||
executable = "/bin/bash"
|
executable="/bin/bash",
|
||||||
)
|
)
|
||||||
self.initialize()
|
self.initialize()
|
||||||
|
|
||||||
|
|
||||||
def debug_code_print(c):
|
def debug_code_print(c):
|
||||||
print("- code: %d, str: %s -"%(
|
print("- code: %d, str: %s -" % (c, str(c)))
|
||||||
c,
|
|
||||||
str(c)
|
|
||||||
))
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
@@ -565,25 +596,25 @@ def start_engines():
|
|||||||
# 53 = pg up
|
# 53 = pg up
|
||||||
# 54 = pg down
|
# 54 = pg down
|
||||||
#
|
#
|
||||||
#~ print(inkey3)
|
# ~ print(inkey3)
|
||||||
#~ sys.exit(0)
|
# ~ sys.exit(0)
|
||||||
|
|
||||||
if inkey in (113, 120, 3, 24, 4): # q, x
|
if inkey in (113, 120, 3, 24, 4): # 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('')
|
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()
|
||||||
if inkey == 47: # /
|
if inkey == 47: # /
|
||||||
entries.edit_menu()
|
entries.edit_menu()
|
||||||
if inkey == 36: # $
|
if inkey == 36: # $
|
||||||
entries.shell()
|
entries.shell()
|
||||||
if inkey == 13: # enter
|
if inkey == 13: # enter
|
||||||
inkey = ord(entries.menu_keys[entries.selected])
|
inkey = ord(entries.menu_keys[entries.selected])
|
||||||
found, message = entries.is_key(chr(inkey))
|
found, message = entries.is_key(chr(inkey))
|
||||||
if found:
|
if found:
|
||||||
@@ -592,7 +623,6 @@ def start_engines():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
entries.initialize()
|
entries.initialize()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
start_engines()
|
start_engines()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import sys,os,re
|
import sys, os, re
|
||||||
import difflib as dl
|
import difflib as dl
|
||||||
|
|
||||||
# Define color codes
|
# Define color codes
|
||||||
@@ -10,61 +10,65 @@ Reset = "\033[0m"
|
|||||||
# Available shortcut keys
|
# Available shortcut keys
|
||||||
key_list = "1234567890qwertyuiop"
|
key_list = "1234567890qwertyuiop"
|
||||||
|
|
||||||
|
|
||||||
class getch:
|
class getch:
|
||||||
def get(self):
|
def get(self):
|
||||||
import termios, tty
|
import termios, tty
|
||||||
|
|
||||||
fd = sys.stdin.fileno()
|
fd = sys.stdin.fileno()
|
||||||
old_settings = termios.tcgetattr(fd)
|
old_settings = termios.tcgetattr(fd)
|
||||||
try:
|
try:
|
||||||
tty.setraw(sys.stdin.fileno())
|
tty.setraw(sys.stdin.fileno())
|
||||||
ch = sys.stdin.read(1)
|
ch = sys.stdin.read(1)
|
||||||
finally:
|
finally:
|
||||||
termios.tcsetattr(
|
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
|
||||||
fd,
|
|
||||||
termios.TCSADRAIN,
|
|
||||||
old_settings
|
|
||||||
)
|
|
||||||
return ch
|
return ch
|
||||||
|
|
||||||
|
|
||||||
def printerr(s):
|
def printerr(s):
|
||||||
sys.stderr.write(s + "\n")
|
sys.stderr.write(s + "\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
|
||||||
def errexit(s):
|
def errexit(s):
|
||||||
printerr(s)
|
printerr(s)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def colorize_matches(directories, repl):
|
def colorize_matches(directories, repl):
|
||||||
return [repl.sub("%s\g<1>%s"%(Green, Reset), d) for d in directories]
|
return [repl.sub("%s\g<1>%s" % (Green, Reset), d) for d in directories]
|
||||||
|
|
||||||
|
|
||||||
def search_close_match(directories, key):
|
def search_close_match(directories, key):
|
||||||
""" Return a list of Components whose name closely matches key """
|
""" Return a list of Components whose name closely matches key """
|
||||||
match = []
|
match = []
|
||||||
key = key.lower()
|
key = key.lower()
|
||||||
for name in directories:
|
for name in directories:
|
||||||
s = dl.SequenceMatcher(
|
s = dl.SequenceMatcher(None, name.lower(), key)
|
||||||
None,
|
|
||||||
name.lower(),
|
|
||||||
key
|
|
||||||
)
|
|
||||||
if s.ratio() > 0:
|
if s.ratio() > 0:
|
||||||
match.append(( s.ratio(), name ))
|
match.append((s.ratio(), name))
|
||||||
match.sort(key = lambda x: x[0], reverse = True)
|
match.sort(key=lambda x: x[0], reverse=True)
|
||||||
best_matches=[x[1] for x in match[0:10]]
|
best_matches = [x[1] for x in match[0:10]]
|
||||||
return best_matches
|
return best_matches
|
||||||
|
|
||||||
|
|
||||||
def get_dirs(pat_dir):
|
def get_dirs(pat_dir):
|
||||||
|
|
||||||
# list sub-folders in the folder
|
# list sub-folders in the folder
|
||||||
current_folders = [d for d in os.listdir(pat_dir) if os.path.isdir(os.path.join(pat_dir, d))]
|
current_folders = [
|
||||||
|
d for d in os.listdir(pat_dir) if os.path.isdir(os.path.join(pat_dir, d))
|
||||||
|
]
|
||||||
current_folders = [d for d in current_folders if not d.startswith(".")]
|
current_folders = [d for d in current_folders if not d.startswith(".")]
|
||||||
current_folders.sort()
|
current_folders.sort()
|
||||||
return current_folders
|
return current_folders
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Print help
|
# Print help
|
||||||
if len(sys.argv) == 1 or sys.argv[-1] == "-h":
|
if len(sys.argv) == 1 or sys.argv[-1] == "-h":
|
||||||
errexit("Guess cd: Find first match in folder, interactive if multiple matches\n Arguments: [dir/]pattern_to_match_folders")
|
errexit(
|
||||||
|
"Guess cd: Find first match in folder, interactive if multiple matches\n Arguments: [dir/]pattern_to_match_folders"
|
||||||
|
)
|
||||||
|
|
||||||
pattern = ".".join(sys.argv[1:])
|
pattern = ".".join(sys.argv[1:])
|
||||||
pat_base = os.path.basename(pattern)
|
pat_base = os.path.basename(pattern)
|
||||||
@@ -74,14 +78,14 @@ def main():
|
|||||||
pat_dir = "."
|
pat_dir = "."
|
||||||
|
|
||||||
if not os.path.exists(pat_dir):
|
if not os.path.exists(pat_dir):
|
||||||
errexit("%s: %sNo such folder%s"%(pat_dir, Red, Reset))
|
errexit("%s: %sNo such folder%s" % (pat_dir, Red, Reset))
|
||||||
|
|
||||||
# list sub-folders in the folder
|
# list sub-folders in the folder
|
||||||
current_folders = get_dirs(pat_dir)
|
current_folders = get_dirs(pat_dir)
|
||||||
|
|
||||||
# no sub-folders
|
# no sub-folders
|
||||||
if len(current_folders) == 0:
|
if len(current_folders) == 0:
|
||||||
errexit("There are no subfolders in %s"%( pat_dir,))
|
errexit("There are no subfolders in %s" % (pat_dir,))
|
||||||
|
|
||||||
# find matches
|
# find matches
|
||||||
match_case = re.compile(".*" + pat_base + ".*")
|
match_case = re.compile(".*" + pat_base + ".*")
|
||||||
@@ -92,8 +96,8 @@ def main():
|
|||||||
|
|
||||||
# no matches, try case insensitive
|
# no matches, try case insensitive
|
||||||
if len(matching_folders) == 0:
|
if len(matching_folders) == 0:
|
||||||
match_nocase = re.compile(".*" + pat_base + ".*",re.I)
|
match_nocase = re.compile(".*" + pat_base + ".*", re.I)
|
||||||
repl_nocase = re.compile("(" + pat_base + ")",re.I)
|
repl_nocase = re.compile("(" + pat_base + ")", re.I)
|
||||||
matching_folders = [d for d in current_folders if match_nocase.match(d)]
|
matching_folders = [d for d in current_folders if match_nocase.match(d)]
|
||||||
matches = colorize_matches(matching_folders, repl_nocase)
|
matches = colorize_matches(matching_folders, repl_nocase)
|
||||||
|
|
||||||
@@ -109,7 +113,7 @@ def main():
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
# Many matches, ask the user for folder index
|
# Many matches, ask the user for folder index
|
||||||
for i,m in enumerate(matches[0:len(key_list)]):
|
for i, m in enumerate(matches[0 : len(key_list)]):
|
||||||
printerr(key_list[i] + ": " + m)
|
printerr(key_list[i] + ": " + m)
|
||||||
|
|
||||||
if len(matches) > len(key_list):
|
if len(matches) > len(key_list):
|
||||||
@@ -120,9 +124,10 @@ def main():
|
|||||||
key_index = key_list.index(key_in)
|
key_index = key_list.index(key_in)
|
||||||
key_match = matching_folders[key_index]
|
key_match = matching_folders[key_index]
|
||||||
except (ValueError, IndexError) as err:
|
except (ValueError, IndexError) as err:
|
||||||
errexit("%s'%s' Not in the list%s"%(Red, key_in, Reset))
|
errexit("%s'%s' Not in the list%s" % (Red, key_in, Reset))
|
||||||
|
|
||||||
print(os.path.join(pat_dir, key_match))
|
print(os.path.join(pat_dir, key_match))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user