Browse Source

moved opts to json file and added a handler for the opts

finished the path abbreviation and picker function
master
Raphael Roberts 7 years ago
parent
commit
1255f7d6f2
  1. 18
      ext_open/ext_open.py
  2. 3
      ext_open/opener.py
  3. 95
      ext_open/opts.json
  4. 138
      ext_open/opts.py
  5. 2
      ext_open/searcher.py
  6. 40
      ext_open/util.py

18
ext_open/ext_open.py

@ -3,6 +3,7 @@ import searcher
import opener
import argparse
from util import picker
import pyperclip
parser = argparse.ArgumentParser(prog='ext-open',prefix_chars=prefix_char)
for opt in prefix:
parser.add_argument(*opt.pop('ostring'),**opt)
@ -25,4 +26,19 @@ if __name__ == '__main__':
matches = s.exact(args.query)
else:
matches = s.search(args.query,args.regex)
row = picker(matches
if len(matches) == 0:
print('No matches')
quit()
if len(matches) == 1:
row = matches[0]
else:
row = picker(matches
path = row[-1]
if args.path:
print(path)
pyperclip.copy(path)
else:
if args.ext == 'exe':
pass #TODO
else:
pass #TODO

3
ext_open/opener.py

@ -5,7 +5,6 @@ import shlex
import subprocess
EDITOR_PATH = config.getpath('global','editor')
EXT = re.compile(r'\.\w+$')
def get_ext(file):
ext = os.path.splitext(file)[-1]
if ext != '':
@ -34,7 +33,7 @@ def standalone(path,params=[],windowless =False,cwd = None):
cmd = cmd = subprocess.list2cmdline([path]+params).replace('"','~')
subprocess.check_output(['cscript.exe',path2windowless,cmd,cwd])
else:
subprocess.Popen([path]+params,cwd=cwd)
def dependant(path,params=[],mode = 'execute',cwd = None):

95
ext_open/opts.json

@ -0,0 +1,95 @@
{
"bools": [
{
"action": "store_true",
"ostring": ["+i", "++case-insensitive"]
},
{
"action": "store_true",
"help": "Search for exact application name",
"ostring": ["+E", "++exact"]
},
{
"action": "store_true",
"help": "Use regex to search",
"ostring": ["+r", "++regex"]
},
{
"action": "store_true",
"help": "Prints path instead of opening application",
"ostring": ["+p", "++path"]
},
{
"action": "store_true",
"help": "Open in editor",
"ostring": ["+e", "++edit"]
}
],
"exe": [
{
"action": "store_true",
"help": "Open windowless",
"ostring": ["+w", "++windowless"]
},
{
"help": "Directory to start in",
"metavar": "dir",
"ostring": ["+d", "++start-in"]
},
{
"help": "Query to search for",
"ostring": ["query"]
},
{
"action": "store",
"help": "Command-line args",
"nargs": "*",
"ostring": ["arg"]
}
],
"exts": [
{
"ext": "py",
"opts": []
},
{
"ext": "java",
"opts": []
}
],
"other": [
{
"help": "Directory to start in",
"metavar": "dir",
"ostring": ["+d", "++start-in"]
},
{
"help": "Query to search for",
"ostring": ["query"]
},
{
"action": "store",
"help": "Command-line args",
"nargs": "*",
"ostring": ["arg"]
}
],
"prefix": [
{
"action": "store_true",
"help": "Update the listings for ext",
"ostring": ["+u", "++update"]
},
{
"help": "Trim backup history, either all or N updates",
"metavar": "(all | N)",
"ostring": ["+t", "++trim-history"]
},
{
"action": "store_true",
"help": "updates the modified times for paths in config\nuseful for ensuring all new files are found",
"ostring": ["+m", "++update-modified-times"]
}
],
"prefix_char": "+"
}

138
ext_open/opts.py

@ -1,53 +1,87 @@
prefix_char = '+'
prefix = [
{
'ostring':['+u','++update'],
'help': 'Update the listings for ext',
'action':'store_true',
},
{
'ostring':['+t','++trim-history'],
'help': 'Trim backup history, either all or N updates',
'metavar': '(all | N)'
},
{
'ostring':['+m','++update-modified-times'],
'action':'store_true',
'help': '''updates the modified times for paths in config
useful for ensuring all new files are found''',
},
]
bools = [
{'action': 'store_true', 'ostring': ['+i', '++case-insensitive']},
{'action': 'store_true', 'help': 'Search for exact application name', 'ostring': ['+E', '++exact']},
{'action': 'store_true', 'help': 'Use regex to search', 'ostring': ['+r', '++regex']},
{'action': 'store_true', 'help': 'Prints path instead of opening application', 'ostring': ['+p', '++path']},
{'action': 'store_true', 'help': 'Open in editor', 'ostring': ['+e', '++edit']},
]
other = [
{'help': 'Directory to start in', 'ostring': ['+d', '++start-in'],'metavar':'dir'},
{'ostring':['query'],'help':'Query to search for'},
{'action': 'store', 'help': 'Command-line args', 'nargs': '*', 'ostring': ['arg']},
]
import json
import os
import copy
class ArgumentHandler:
def __init__(self,args_file):
self.args_file = args_file
self.exts = set()
with open(self.args_file) as file:
self.data = json.load(file)
for _ext in self.data['exts']:
ext = _ext['ext']
self.exts.add(ext)
args = _ext['opts']
self.set(ext,ArgumentContainer(args))
for key,value in self.data.items():
if key != 'exts' and isinstance(value,list):
self.set(key,ArgumentContainer(value))
self.prefix_char = self.data['prefix_char']
def get(self,item):
return self.__dict__[item]
def set(self,item,value):
self.__dict__[item] = value
def save(self):
data = []
for ext in self.exts:
data.append({'ext':ext,'opts':self.get(ext).to_dict()})
valid = set(self.__dict__.keys()) - self.exts
valid -= {'self.args_file'}
for key in valid:
value = self.get(key)
if isinstance(value,str):
self.data[key] = value
elif isinstance(value,ArgumentContainer):
self.data[key] = value.to_dict()
def add_ext(self,ext):
self.set(ext,ArgumentContainer([]))
self.exts.add(ext)
def commit(self):
backup_name = self.args_file + '.bak'
if os.path.exists(backup_name):
os.remove(backup_name)
os.copy(self.args_file,self.backup_name)
with open(self.args_file,'w') as file:
json.dump(self.data,file)
def revert(self):
backup_name = self.args_file + '.bak'
if os.path.exists(backup_name):
os.remove(self.args_file)
os.rename(backup_name,self.args_file)
class ArgumentContainer:
def __init__(self,l_of_args):
self.args = l_of_args
def add_argument(self,*args,**kwargs):
new_arg = {
'ostring': args,
}
new_arg.update(kwargs)
self.args.append(new_arg)
def to_dict(self):
return copy.deepcopy(self.args)
def __str__(self):
ostrings = (opt['ostring'] for opt in self.args)
f_ostrings = ('({})'.format(', '.join(ostring)) for ostring in ostrings)
return '[{}]'.format(', '.join(f_ostrings))
def __repr__(self):
return str(self)
cur = ArgumentHandler('opts.json')
globals().update(cur.data)
common = bools+other
exts = [
{
'ext' : 'py',
'opts' : []
},
{
'ext' : 'java',
'opts': []
}
]
exe = [
{
'ostring':['+w','++windowless'],
'help': 'Open windowless',
'action': 'store_true',
},
{'help': 'Directory to start in', 'ostring': ['+d', '++start-in'],'metavar':'dir'},
{'ostring':['query'],'help':'Query to search for'},
{'action': 'store', 'help': 'Command-line args', 'nargs': '*', 'ostring': ['arg']},
]

2
ext_open/searcher.py

@ -76,7 +76,7 @@ class Searcher:
else:
self.cur.execute('SELECT name,fullpath FROM {} WHERE INSIDE(?,name,?)=1;'.format(self.ext),[query,self.case])
return self.cur.fetchall()
def exact(self,query):
self.cur.execute('SELECT name,fullpath FROM {} WHERE name=?'.format(self.ext),[query])
return self.cur.fetchall()

40
ext_open/util.py

@ -3,7 +3,8 @@ import datetime
from pydoc import pager
import os
import re
from config import config
windows_path = re.compile(r"[a-zA-Z]\:(\\[^/\\?\%\*\:\|\"\<\>]+)+")
# https://stackoverflow.com/a/827397
def is_admin():
return windll.shell32.IsUserAnAdmin() != 0
@ -33,7 +34,7 @@ def no_parents(paths):
paths.append(path)
return ret
def abbreviate(path,n=72):
def abbreviate(path,n=72,min_path = 2):
if len(path) > n:
elements = []
b = os.path.basename(path)
@ -47,19 +48,30 @@ def abbreviate(path,n=72):
l = len(elements)
prefix = elements[:l//2]
postfix = elements[l//2:]
while len(os.path.join(*prefix,'...',*postfix))
res = os.path.join(*prefix,'...',*postfix)
while len(res) > n and (len(prefix)> min_path or len(postfix) > min_path):
if len(postfix) > len(prefix):
postfix = postfix[1:]
else:
prefix = prefix[:-1]
res = os.path.join(*prefix,'...',*postfix)
return res
else:
return path
def str_coerce(s,**kwargs):
if isinstance(s,datetime.datetime):
return s.strftime(kwargs['datetime_format'])
elif isinstance(s,(int,float)):
return str(s)
elif windows_path.match(s):
return abbreviate(s,kwargs['path_length'],kwargs['min_path'])
else:
return str(s)
def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer = ' ',bottom = '=',l_end = '|',r_end = '|',interactive = False):
l = [[str_coerce(s,datetime_format = datetime_format) for s in row] for row in l]
n = config.getint('global','path_length',fallback=80)
min_path = config.getint('global','min_path',fallback = 2)
l = [[str_coerce(s,datetime_format = datetime_format,path_length=n,min_path=min_path) for s in row] for row in l]
max_col = []
for row in l:
for i,col in enumerate(row):
@ -78,7 +90,6 @@ def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer
for row in l:
content = seperator.join(col.ljust(max_col[i],spacer if i < len(row)-1 or r_end else ' ') for i,col in enumerate(row))
done.append(fmt_row.format(content = content))
if bottom:
bottom = bottom*len(done[0])
row_sep = ('\n'+bottom+'\n')
@ -97,25 +108,24 @@ def print2d(l,datetime_format = "%A, %B %e, %Y %H:%M:%S",seperator= ' | ',spacer
def picker(rows,interactive=False):
opts = {
'spacer':' ',
'seperator':' ',
'seperator':' | ',
'interactive': interactive,
'bottom':'=',
'l_end':'<',
'r_end':'>',
}
drows = ( (i,)+row for i,row in enumerate(rows))
print2d(drows,**opts)
res = print2d(drows,**opts)
if not interactive:
print(res)
which = None
while not which:
while which is None:
try:
which = input('Which one?: ')
except KeyboardInterrupt:
quit()
try:
which = srt_keys[int(which)]
which = int(which)
except ValueError:
which = None
return rows[which]
if __name__ == "__main__":
abbreviate(os.getcwd())
Loading…
Cancel
Save