fix fzf find

pull/29/head
deadc0de6 2 years ago
parent f782078c3d
commit d8a360d3b5

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

@ -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"""

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

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

Loading…
Cancel
Save