2
1
mirror of https://github.com/deadc0de6/catcli synced 2024-11-13 07:10:26 +00:00

fix fzf find

This commit is contained in:
deadc0de6 2022-10-21 23:06:54 +02:00
parent f782078c3d
commit d8a360d3b5
4 changed files with 83 additions and 55 deletions

View File

@ -20,6 +20,7 @@ from .catalog import Catalog
from .walker import Walker
from .noder import Noder
from .utils import ask, edit
from .exceptions import BadFormatException, CatcliException
NAME = 'catcli'
CUR = os.path.dirname(os.path.abspath(__file__))
@ -33,6 +34,7 @@ BANNER = f""" +-+-+-+-+-+-+
|c|a|t|c|l|i|
+-+-+-+-+-+-+ v{VERSION}"""
# TODO add grep format for output
USAGE = f"""
{BANNER}
@ -155,7 +157,7 @@ def cmd_ls(args, noder, top):
fmt = args['--format']
if fmt.startswith('fzf'):
raise Exception('fzf is not supported in ls')
raise BadFormatException('fzf is not supported in ls, use find')
found = noder.walk(top, path,
rec=args['--recursive'],
fmt=fmt,
@ -188,9 +190,9 @@ def cmd_find(args, noder, top):
raw = args['--raw-size']
script = args['--script']
search_for = args['<term>']
return noder.find_name(top, search_for, script=script,
startpath=startpath, directory=directory,
parentfromtree=fromtree, fmt=fmt, raw=raw)
noder.find_name(top, search_for, script=script,
startpath=startpath, directory=directory,
parentfromtree=fromtree, fmt=fmt, raw=raw)
def cmd_tree(args, noder, top):
@ -261,9 +263,9 @@ def print_supported_formats():
"""print all supported formats to stdout"""
print('"native" : native format')
print('"csv" : CSV format')
print(f' {Noder.CSV_HEADER}')
print('"fzf-native" : fzf with native output for selected entries')
print('"fzf-csv" : fzf with native output for selected entries')
print(f' {Noder.CSV_HEADER}')
print('"fzf-native" : fzf to native (only for find)')
print('"fzf-csv" : fzf to csv (only for find)')
def main():
@ -331,7 +333,7 @@ def main():
cmd_rename(args, catalog, top)
elif args['edit']:
cmd_edit(args, noder, catalog, top)
except Exception as exc:
except CatcliException as exc:
Logger.out_err('ERROR ' + str(exc))
return False

14
catcli/exceptions.py Normal file
View File

@ -0,0 +1,14 @@
"""
author: deadc0de6 (https://github.com/deadc0de6)
Copyright (c) 2022, deadc0de6
Catcli exceptions
"""
class CatcliException(Exception):
"""generic catcli exception"""
class BadFormatException(CatcliException):
"""use of bad format"""

View File

@ -402,7 +402,6 @@ class Noder:
Logger.dir(pre, name, depth=depth, attr=attr)
elif node.type == self.TYPE_STORAGE:
# node of type storage
szfree = size_to_str(node.free, raw=raw)
sztotal = size_to_str(node.total, raw=raw)
szused = size_to_str(node.total - node.free, raw=raw)
nbchildren = len(node.children)
@ -438,7 +437,7 @@ class Noder:
else:
Logger.err(f'bad node encountered: {node}')
def print_tree(self, top, node,
def print_tree(self, node,
fmt='native',
raw=False):
"""
@ -455,14 +454,11 @@ class Noder:
self._print_node(thenode, pre=pre, withdepth=True, raw=raw)
elif fmt == 'csv':
# csv output
self._to_csv(node, with_header=header, raw=raw)
self._to_csv(node, raw=raw)
elif fmt == 'csv-with-header':
# csv output
Logger.out(self.CSV_HEADER)
self._to_csv(node, with_header=header, raw=raw)
elif fmt.startswith('fzf'):
# flat
self._to_fzf(top, node, fmt)
self._to_csv(node, raw=raw)
def _to_csv(self, node, raw=False):
"""print the tree to csv"""
@ -476,10 +472,9 @@ class Noder:
selected = fzf.prompt(strings)
return selected
def _to_fzf(self, top, node, fmt):
def _to_fzf(self, node, fmt):
"""
print node to fzf
@top: top node
@node: node to start with
@fmt: output format for selected nodes
"""
@ -503,7 +498,7 @@ class Noder:
if path not in nodes:
continue
rend = nodes[path]
self.print_tree(top, rend, fmt=subfmt)
self.print_tree(rend, fmt=subfmt)
def to_dot(self, node, path='tree.dot'):
"""export to dot for graphing"""
@ -529,72 +524,81 @@ class Noder:
@fmt: output format
@raw: raw size output
"""
## TODO error with fzf
self._debug(f'searching for \"{key}\"')
if not key:
# nothing to search for
return None
# search for nodes based on path
start = top
if startpath:
start = self.get_node(top, startpath)
found = anytree.findall(start, filter_=self._callback_find_name(key))
filterfunc = self._callback_find_name(key, directory)
found = anytree.findall(start, filter_=filterfunc)
nbfound = len(found)
self._debug(f'found {nbfound} node(s)')
# compile found nodes
paths = {}
nodes = []
for item in found:
if item.type == self.TYPE_STORAGE:
# ignore storage nodes
continue
if directory and item.type != self.TYPE_DIR:
# ignore non directory
continue
nodes.append(item)
item = self._sanitize(item)
if parentfromtree:
paths[self._get_parents(item)] = item
else:
paths[item.relpath] = item
if fmt == 'native':
for item in nodes:
self._print_node(item, withpath=True,
withdepth=True,
withstorage=True,
recalcparent=parentfromtree,
raw=raw)
elif fmt.startswith('csv'):
if fmt == 'csv-with-header':
Logger.out(self.CSV_HEADER)
for item in nodes:
self._node_to_csv(item, raw=raw)
elif fmt.startswith('fzf'):
selected = self._fzf_prompt(paths)
# handle fzf mode
if fmt.startswith('fzf'):
selected = self._fzf_prompt(paths.keys())
newpaths = {}
subfmt = fmt.replace('fzf-', '')
for item in selected:
if item not in paths:
continue
newpaths[item] = paths[item]
self.print_tree(top, newpaths[item], fmt=subfmt)
self.print_tree(newpaths[item], fmt=subfmt)
paths = newpaths
else:
if fmt == 'native':
for _, item in paths.items():
self._print_node(item, withpath=True,
withdepth=True,
withstorage=True,
recalcparent=parentfromtree,
raw=raw)
elif fmt.startswith('csv'):
if fmt == 'csv-with-header':
Logger.out(self.CSV_HEADER)
for _, item in paths.items():
self._node_to_csv(item, raw=raw)
# execute script if any
if script:
tmp = ['${source}/' + x for x in paths]
tmpstr = ' '.join(tmp)
cmd = f'op=file; source=/media/mnt; $op {tmpstr}'
Logger.info(cmd)
return found
def _callback_find_name(self, term):
def _callback_find_name(self, term, directory):
"""callback for finding files"""
def find_name(node):
if node.type == self.TYPE_STORAGE:
# ignore storage nodes
return False
if node.type == self.TYPE_TOP:
# ignore top nodes
return False
if node.type == self.TYPE_META:
# ignore meta nodes
return False
if directory and node.type != self.TYPE_DIR:
# ignore non directory
return False
# filter
if not term:
return True
if term.lower() in node.name.lower():
return True
# ignore
return False
return find_name
@ -623,7 +627,7 @@ class Noder:
if rec:
# print the entire tree
self.print_tree(top, found[0].parent, fmt=fmt, raw=raw)
self.print_tree(found[0].parent, fmt=fmt, raw=raw)
return found
# sort found nodes
@ -650,7 +654,7 @@ class Noder:
elif fmt.startswith('csv'):
self._node_to_csv(item, raw=raw)
elif fmt.startswith('fzf'):
self._to_fzf(top, item, fmt)
self._to_fzf(item, fmt)
except anytree.resolver.ChildResolverError:
pass
@ -732,6 +736,14 @@ class Noder:
"""return md5 hash of node"""
return md5sum(path)
def _sanitize(self, node):
"""sanitize node string"""
node.name = node.name.encode('utf-8',
errors='ignore').decode('utf-8')
node.relpath = node.relpath.encode('utf-8',
errors='ignore').decode('utf-8')
return node
def _debug(self, string):
"""print debug"""
if not self.debug:

View File

@ -78,7 +78,7 @@ class TestUpdate(unittest.TestCase):
self.assertTrue(nod.md5 == f4_md5)
# print catalog
noder.print_tree(top, top)
noder.print_tree(top)
# add some files and directories
new1 = create_rnd_file(dir1, 'newf1')
@ -120,7 +120,7 @@ class TestUpdate(unittest.TestCase):
# print catalog
# print(read_from_file(catalogpath))
noder.print_tree(top, top)
noder.print_tree(top)
# explore the top node to find all nodes
self.assertTrue(len(top.children) == 1)