192 lines
6.6 KiB
Python
192 lines
6.6 KiB
Python
import os
|
|
import yaml
|
|
import shutil
|
|
|
|
class OrvaniTag:
|
|
|
|
INDEX = {}
|
|
DB = dict()
|
|
FILENAME = ''
|
|
FILE = ''
|
|
CTX = {
|
|
'contexts' : '@',
|
|
'projects' : '+',
|
|
'tags' : '#'
|
|
}
|
|
|
|
def __init__(self, path: str='context.yaml', contexts=CTX):
|
|
self.FILENAME = os.path.basename(path)
|
|
self.INDEX = self.CTX.copy()
|
|
for ctx in self.INDEX:
|
|
self.INDEX[ctx] = {}
|
|
self.INDEX['files'] = {}
|
|
self.__cd('')
|
|
|
|
def __cd(self, path: str):
|
|
"""change file context to subdirectory"""
|
|
self.FILE = os.path.join(path, self.FILENAME)
|
|
if os.path.isfile(self.FILE):
|
|
try:
|
|
with open(self.FILE, 'r') as data:
|
|
self.DB = yaml.safe_load(data)
|
|
except Exception:
|
|
print('File does not exist')
|
|
else:
|
|
self.DB = dict()
|
|
|
|
def __save(self):
|
|
"""save context file to current directory"""
|
|
try:
|
|
with open(self.FILE, 'w+') as data:
|
|
yaml.dump(self.DB, data)
|
|
except Exception:
|
|
print('File write error')
|
|
|
|
def __context(self, argv) -> dict:
|
|
"""create context for given filename"""
|
|
context = dict()
|
|
for ctx in self.CTX.keys():
|
|
context.update( { ctx : []})
|
|
for arg in argv:
|
|
for ctx in self.CTX.keys():
|
|
if str(arg)[0] in self.CTX.values():
|
|
if str(arg).startswith(self.CTX[ctx]):
|
|
context[ctx].append(str(arg)[1:])
|
|
else:
|
|
context.update( { 'note' : str(arg)})
|
|
return context
|
|
|
|
def add(self, file: str, *argv: str):
|
|
if os.path.isfile(file):
|
|
if os.path.dirname(file):
|
|
self.__cd(os.path.dirname(file))
|
|
file = os.path.basename(file)
|
|
context = self.__context(argv)
|
|
if file in self.DB:
|
|
for ctx in self.CTX.keys():
|
|
self.DB[file][ctx] = list(set( self.DB[file][ctx] + context[ctx]))
|
|
if 'note' in context.keys():
|
|
self.DB[file]['note'] = context['note']
|
|
else:
|
|
self.DB.update( { file : context } )
|
|
self.__save()
|
|
|
|
def remove(self, file: str, *argv: str):
|
|
if os.path.isfile(file):
|
|
if os.path.dirname(file):
|
|
self.__cd(os.path.dirname(file))
|
|
file = os.path.basename(file)
|
|
context = self.__context(argv)
|
|
if file in self.DB:
|
|
for ctx in self.CTX.keys():
|
|
for item in context[ctx]:
|
|
if item in self.DB[file][ctx]:
|
|
self.DB[file][ctx].remove(item)
|
|
self.__save()
|
|
|
|
def delete(self, file: str, fop:bool=False):
|
|
if os.path.dirname(file):
|
|
self.__cd(os.path.dirname(file))
|
|
if fop:
|
|
os.remove(file)
|
|
file = os.path.basename(file)
|
|
if file in self.DB:
|
|
del self.DB[file]
|
|
self.__save()
|
|
|
|
def move(self, source: str, dest: str, retain: bool=False, fop: bool=True):
|
|
if os.path.isfile(source) and os.path.isdir(os.path.dirname(dest)):
|
|
sourcefolder = os.path.dirname(source)
|
|
sourcefile = os.path.basename(source)
|
|
destfolder = os.path.dirname(dest)
|
|
destfile = os.path.basename(dest)
|
|
if not destfile:
|
|
destfile = sourcefile
|
|
sourcedata = {}
|
|
self.__cd(sourcefolder)
|
|
if self.DB[sourcefile]:
|
|
sourcedata = self.DB[sourcefile]
|
|
if not retain:
|
|
self.purge(source)
|
|
self.__cd(destfolder)
|
|
self.DB.update( { destfile : sourcedata } )
|
|
self.__save()
|
|
if fop:
|
|
if retain:
|
|
shutil.copy2(source, dest)
|
|
else:
|
|
shutil.move(source, dest, copy_function=shutil.copy2)
|
|
|
|
def purge(self, path: str=''):
|
|
if os.path.dirname(path):
|
|
self.__cd(os.path.dirname(path))
|
|
for file in self.DB.keys():
|
|
if not os.path.isfile(file):
|
|
if file in self.DB:
|
|
del self.DB[file]
|
|
self.__save()
|
|
if not self.DB:
|
|
os.remove(self.FILE)
|
|
|
|
def list(self, search: str, path: str='./', filter=None, exact=True, recursive: bool=True, cache: bool=False):
|
|
if path == '':
|
|
path = './'
|
|
if not os.path.dirname(path):
|
|
path += '/'
|
|
cachefile = os.path.join(path, 'index.yaml')
|
|
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')
|
|
else:
|
|
self.__indexfolder(path)
|
|
if recursive:
|
|
for (root,dirs,files) in os.walk(path):
|
|
if dirs:
|
|
for dir in dirs:
|
|
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')
|
|
result = {
|
|
'index' : self.INDEX,
|
|
'found' : []
|
|
}
|
|
for ctx in self.CTX.keys():
|
|
for context in self.INDEX[ctx]:
|
|
if filter and not filter == ctx:
|
|
continue
|
|
if exact:
|
|
if search == context:
|
|
result['found'] = self.INDEX[ctx][context]
|
|
else:
|
|
if search in context:
|
|
result['found'] = self.INDEX[ctx][context]
|
|
return result
|
|
|
|
def __indexfolder(self, sub: str):
|
|
if os.path.dirname(sub):
|
|
self.__cd(sub)
|
|
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]:
|
|
if item:
|
|
filelist = [path]
|
|
if ctx in self.INDEX:
|
|
if item in self.INDEX[ctx]:
|
|
filelist += self.INDEX[ctx][item]
|
|
self.INDEX.update( { ctx : { item : filelist } } )
|
|
|
|
|
|
o = OrvaniTag()
|
|
r = o.list('markdown', cache=True)
|
|
print(r)
|