modularized, bugfixes

This commit is contained in:
randogoth 2023-06-07 13:28:28 +03:00
parent 3a5633603b
commit 40026a3c0d
7 changed files with 191 additions and 186 deletions

6
.context.yaml Normal file
View file

@ -0,0 +1,6 @@
files:
TODO.md:
contexts: []
projects:
- bokertov
tags: []

2
orvani/__init__.py Normal file
View file

@ -0,0 +1,2 @@
from .orvani import OrvaniTag
from .cmd import main

Binary file not shown.

140
orvani/cmd.py Normal file
View file

@ -0,0 +1,140 @@
import os
import sys
from argparse import ArgumentParser as argp, SUPPRESS, RawTextHelpFormatter as raw
from pathlib import Path
from rich.console import Console
from rich.table import Table
from orvani import OrvaniTag, CONTEXT_FILE, CACHE_FILE
def mktable(query: str, index: dict):
console = Console()
if len(index['found']) > 0:
table = Table(title=f"Results for `{query}`")
table.add_column("Path", justify="right", style="white", no_wrap=True)
table.add_column("Note", style="#cccccc")
table.add_column("Projects", justify="center", style="cyan")
table.add_column("Contexts", justify="center", style="magenta")
table.add_column("Tags", justify="center", style="green")
note = tags = projects = contexts = tags = ''
for file in index['found']:
path = file
fc = index['index']['files'][file]
if 'note' in fc:
note = fc['note']
else:
note = ''
tags = ' '.join(['#' + tag for tag in fc['tags']])
projects = ' '.join(['+' + p for p in fc['projects']])
contexts = ' '.join(['@' + c for c in fc['contexts']])
table.add_row(path, note, projects, contexts, tags)
console.print(table)
else:
console.print(f"No results found for `{query}`", style="red")
def main():
command_help = """{add,a} FILE [CONTEXT ...]
{remove,rem,r} FILE [CONTEXT ...]
{copy,cp} SOURCE DEST
{move,mv} SOURCE DEST
{del,rm} FILE
{clear,c} FILE
{clean} PATH
{list,ls,dir,l} QUERY
{listproj,lsprj} QUERY
{listcon,lsc} QUERY
{listtag,lst} QUERY
"""
p = argp(description="OrvaniTagger", formatter_class=raw)
p.add_argument("--not-recursive", "-nr", action="store_false", help="Include subdirectories in search")
p.add_argument("--no-file_operation", "-nf", action="store_false", help="Copy/Move/Delete file, not just context")
p.add_argument("--path", "-p", action="store", type=str, help="List/search custom path", default='')
p.add_argument("--exact", "-e", action="store_true", help="Match exact search term")
p.add_argument("--cache", action="store_true", help="Cache index search (useful with deep directory trees)")
p.add_argument("--context_filter", "-c", action="store", type=str, help="Filter context", choices=['context', 'project', 'tag'], default=None)
p.add_argument("command", nargs="?", default=None, metavar='Command',
help=command_help, type=str,
choices=[
'add', 'a',
'remove', 'rem', 'r',
'list', 'ls', 'dir', 'l',
'copy', 'cp',
'move', 'mv',
'del', 'rm',
'clear', 'c',
'listproj', 'lsprj',
'listcon', 'lsc',
'listtag', 'lst',
'clean', 'purge',
'read'
])
p.add_argument("file", nargs="?", type=str, help=SUPPRESS)
p.add_argument("context", nargs="*", type=str, help=SUPPRESS)
p.print_usage = p.print_help
args = p.parse_args()
orvani = OrvaniTag()
if args.command in ['add', 'a']:
if args.file and args.context:
orvani.add(args.file, *args.context)
elif args.command in ['remove', 'rem', 'r']:
if args.file and args.context:
orvani.remove(args.file, *args.context)
elif args.command in ['list', 'ls', 'dir', 'l', 'listproj', 'lsprj', 'lp', 'listcon', 'lsc', 'lc', 'listtag', 'lst', 'lt']:
query = [args.file] + args.context
if args.command in ['listproj', 'lsprj', 'lp'] or args.context_filter == 'project':
args.context_filter = 'projects'
if args.command in ['listcon', 'lsc', 'lc'] or args.context_filter == 'context':
args.context_filter = 'contexts'
if args.command in ['listtag', 'lst', 'lt'] or args.context_filter == 'tag':
args.context_filter = 'tags'
if query:
r = orvani.list(args.path, args.context_filter, args.exact, args.not_recursive, args.cache, *query)
mktable(' '.join(sys.argv[1:]), r)
elif args.command in ['copy', 'cp']:
if args.file and args.context:
orvani.move(args.file, args.context[0], True, args.no_file_operation)
elif args.command in ['move', 'mv']:
if args.file and args.context:
orvani.move(args.file, args.context[0], False, args.no_file_operation)
elif args.command in ['del', 'rm']:
if args.file:
orvani.delete(args.file, args.no_file_operation)
elif args.command in ['purge']:
if not args.file:
args.file = '.'
target = Path(args.file)
context_file = target / CONTEXT_FILE
cache_file = target / CACHE_FILE
context_file.unlink(missing_ok=True)
cache_file.unlink(missing_ok=True)
if args.not_recursive:
for (root,dirs,files) in os.walk(args.file):
if dirs:
for dir in dirs:
rpath = os.path.join(root, dir)
Path(CONTEXT_FILE).unlink(missing_ok=True)
Path(CACHE_FILE).unlink(missing_ok=True)
elif args.command in ['clean']:
if not args.file:
args.file = ''
orvani.purge(args.file, args.not_recursive)
elif args.command in ['read']:
orvani.read_meta()
if __name__ == '__main__':
main()

View file

@ -1,12 +1,7 @@
import os
import sys
import yaml
import shutil
from pathlib import Path
from argparse import ArgumentParser as argp, SUPPRESS, RawTextHelpFormatter as raw
from rich.console import Console
from rich.table import Table
import frontmatter
# Defaults
@ -73,9 +68,8 @@ class OrvaniTag:
y = { 'files' : self.DB }
if self.CONFIG:
y['config'] = self.CONFIG
if Path(self.FILE).is_file():
with Path(self.FILE).open('w') as data:
yaml.safe_dump(y, data)
with Path(self.FILE).open('w+') as data:
yaml.safe_dump(y, data)
def __context(self, argv) -> dict:
@ -117,14 +111,15 @@ class OrvaniTag:
if target.exists():
self.__cd(target.parent.name)
context = self.__context(argv)
if file in self.DB:
if target.name in self.DB:
for ctx in self.CTX.keys():
if self.CTX[ctx] != None:
self.DB[file][ctx] = list(set( self.DB[file][ctx] + context[ctx]))
self.DB[target.name][ctx] = list(set( self.DB[target.name][ctx] + context[ctx]))
else:
self.DB[file][ctx] = context[ctx]
if ctx in context:
self.DB[target.name][ctx] = context[ctx]
else:
self.DB.update( { file : context } )
self.DB.update( { target.name : context } )
self.__save()
def remove(self, file: str, *argv: str):
@ -241,8 +236,6 @@ class OrvaniTag:
"""
if path == '':
path = './'
if not os.path.dirname(path):
path += '/'
self.__makeindex(path, recursive, cache)
result = self.__search(search, exact)
return result
@ -272,13 +265,9 @@ class OrvaniTag:
recursive (bool): traverse subdirectories
"""
cachefile = os.path.join(path, self.CACHEFILE)
if cache and os.path.isfile(cachefile):
try:
with open(cachefile, 'r') as cache:
self.INDEX = yaml.safe_load(cache)
except Exception:
print('File does not exist')
cachefile = Path(path) / self.CACHEFILE
if cache and cachefile.is_file():
self.INDEX = yaml.safe_load(cachefile.read_text())
else:
self.__indexfolder(path)
if recursive:
@ -288,11 +277,8 @@ class OrvaniTag:
rpath = os.path.join(root, dir)
self.__indexfolder(rpath)
if cache:
try:
with open(cachefile, 'w+') as data:
yaml.dump(self.INDEX, data)
except Exception:
print('File write error')
with open(cachefile, 'w+') as data:
yaml.dump(self.INDEX, data)
def __indexfolder(self, sub: str):
"""
@ -301,19 +287,21 @@ class OrvaniTag:
sub (str): path of folder
"""
if os.path.dirname(sub):
self.__cd(sub)
target = Path(sub)
if target.is_dir():
self.__cd(target.name)
if self.DB:
for file in self.DB.keys():
path = os.path.join(sub, file)
self.INDEX['files'].update( { path : self.DB[file]} )
for ctx in self.CTX.keys():
for item in self.DB[file][ctx]:
filelist = [path]
if ctx in self.INDEX:
if item in self.INDEX[ctx]:
filelist += self.INDEX[ctx][item]
self.INDEX[ctx][item] = filelist
if ctx in self.DB[file]:
for item in self.DB[file][ctx]:
filelist = [path]
if ctx in self.INDEX:
if item in self.INDEX[ctx]:
filelist += self.INDEX[ctx][item]
self.INDEX[ctx][item] = filelist
def __search(self, search, filter: str=None, exact:bool=False):
"""
@ -335,25 +323,17 @@ class OrvaniTag:
for context in self.INDEX[ctx]:
if filter and not filter == ctx:
continue
for q in query[ctx]:
if exact:
if q == context:
if self.INDEX[ctx][context] not in ret[ctx]:
ret[ctx] += self.INDEX[ctx][context]
else:
if q in context:
if self.INDEX[ctx][context] not in ret[ctx]:
ret[ctx] += self.INDEX[ctx][context]
if exact:
if 'note' in query and query['note'] == context:
if self.INDEX[ctx][context] not in ret['note']:
ret['note'] += self.INDEX[ctx][context]
else:
if 'note' in query and query['note'] in context:
if self.INDEX[ctx][context] not in ret['note']:
ret['note'] += self.INDEX[ctx][context]
if ctx in query:
for q in query[ctx]:
if exact:
if q == context:
if self.INDEX[ctx][context] not in ret[ctx]:
ret[ctx] += self.INDEX[ctx][context]
else:
if q in context:
if self.INDEX[ctx][context] not in ret[ctx]:
ret[ctx] += self.INDEX[ctx][context]
ret[ctx] = list(set(ret[ctx]))
ret['note'] = list(set(ret['note']))
if len(search) > 1:
result['found'] = sorted(list(set(self.__intersect(ret))), key=lambda x: x.count('/'))
else:
@ -376,137 +356,4 @@ class OrvaniTag:
def read_meta(self):
for callback in self.META_IN:
entry = callback(self.CONFIG, self.DB)
print(entry)
def mktable(query: str, index: dict):
console = Console()
if len(index['found']) > 0:
table = Table(title=f"Results for `{query}`")
table.add_column("Path", justify="right", style="white", no_wrap=True)
table.add_column("Note", style="#cccccc")
table.add_column("Projects", justify="center", style="cyan")
table.add_column("Contexts", justify="center", style="magenta")
table.add_column("Tags", justify="center", style="green")
note = tags = projects = contexts = tags = ''
for file in index['found']:
path = file
fc = index['index']['files'][file]
if 'note' in fc:
note = fc['note']
else:
note = ''
tags = ' '.join(['#' + tag for tag in fc['tags']])
projects = ' '.join(['+' + p for p in fc['projects']])
contexts = ' '.join(['@' + c for c in fc['contexts']])
table.add_row(path, note, projects, contexts, tags)
console.print(table)
else:
console.print(f"No results found for `{query}`", style="red")
def main():
command_help = """{add,a} FILE [CONTEXT ...]
{remove,rem,r} FILE [CONTEXT ...]
{copy,cp} SOURCE DEST
{move,mv} SOURCE DEST
{del,rm} FILE
{clear,c} FILE
{clean} PATH
{list,ls,dir,l} QUERY
{listproj,lsprj} QUERY
{listcon,lsc} QUERY
{listtag,lst} QUERY
"""
p = argp(description="OrvaniTagger", formatter_class=raw)
p.add_argument("--not-recursive", "-nr", action="store_false", help="Include subdirectories in search")
p.add_argument("--no-file_operation", "-nf", action="store_false", help="Copy/Move/Delete file, not just context")
p.add_argument("--path", "-p", action="store", type=str, help="List/search custom path", default='')
p.add_argument("--exact", "-e", action="store_true", help="Match exact search term")
p.add_argument("--cache", action="store_true", help="Cache index search (useful with deep directory trees)")
p.add_argument("--context_filter", "-c", action="store", type=str, help="Filter context", choices=['context', 'project', 'tag'], default=None)
p.add_argument("command", nargs="?", default=None, metavar='Command',
help=command_help, type=str,
choices=[
'add', 'a',
'remove', 'rem', 'r',
'list', 'ls', 'dir', 'l',
'copy', 'cp',
'move', 'mv',
'del', 'rm',
'clear', 'c',
'listproj', 'lsprj',
'listcon', 'lsc',
'listtag', 'lst',
'clean', 'purge',
'read'
])
p.add_argument("file", nargs="?", type=str, help=SUPPRESS)
p.add_argument("context", nargs="*", type=str, help=SUPPRESS)
p.print_usage = p.print_help
args = p.parse_args()
orvani = OrvaniTag()
if args.command in ['add', 'a']:
if args.file and args.context:
orvani.add(args.file, *args.context)
elif args.command in ['remove', 'rem', 'r']:
if args.file and args.context:
orvani.remove(args.file, *args.context)
elif args.command in ['list', 'ls', 'dir', 'l', 'listproj', 'lsprj', 'lp', 'listcon', 'lsc', 'lc', 'listtag', 'lst', 'lt']:
query = [args.file] + args.context
if args.command in ['listproj', 'lsprj', 'lp'] or args.context_filter == 'project':
args.context_filter = 'projects'
if args.command in ['listcon', 'lsc', 'lc'] or args.context_filter == 'context':
args.context_filter = 'contexts'
if args.command in ['listtag', 'lst', 'lt'] or args.context_filter == 'tag':
args.context_filter = 'tags'
if query:
r = orvani.list(args.path, args.context_filter, args.exact, args.not_recursive, args.cache, *query)
mktable(' '.join(sys.argv[1:]), r)
elif args.command in ['copy', 'cp']:
if args.file and args.context:
orvani.move(args.file, args.context[0], True, args.no_file_operation)
elif args.command in ['move', 'mv']:
if args.file and args.context:
orvani.move(args.file, args.context[0], False, args.no_file_operation)
elif args.command in ['del', 'rm']:
if args.file:
orvani.delete(args.file, args.no_file_operation)
elif args.command in ['purge']:
if not args.file:
args.file = '.'
target = Path(args.file)
context_file = target / CONTEXT_FILE
cache_file = target / CACHE_FILE
context_file.unlink(missing_ok=True)
cache_file.unlink(missing_ok=True)
if args.not_recursive:
for (root,dirs,files) in os.walk(args.file):
if dirs:
for dir in dirs:
rpath = os.path.join(root, dir)
Path(CONTEXT_FILE).unlink(missing_ok=True)
Path(CACHE_FILE).unlink(missing_ok=True)
elif args.command in ['clean']:
if not args.file:
args.file = ''
orvani.purge(args.file, args.not_recursive)
elif args.command in ['read']:
orvani.read_meta()
if __name__ == '__main__':
main()
print(entry)

10
test/.context.yaml Normal file
View file

@ -0,0 +1,10 @@
files:
test.txt:
contexts:
- test
note: frrr
projects:
- test
tags:
- faa
- test

0
test/test.txt Normal file
View file