modularized list method
This commit is contained in:
parent
ef12ef0091
commit
42c9cbf002
7 changed files with 90 additions and 51 deletions
|
|
@ -2,11 +2,9 @@ TODO.md:
|
|||
contexts: []
|
||||
note: The TODO file of this project
|
||||
projects:
|
||||
- tagg
|
||||
- tagger
|
||||
tags:
|
||||
- frr
|
||||
- tag2
|
||||
- tag1
|
||||
orvani.py:
|
||||
contexts:
|
||||
- private
|
||||
|
|
|
|||
26
README.md
Normal file
26
README.md
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Orvani Tagger
|
||||
|
||||
(From עוֹרְבָנִי, the Hebrew name for th Eurasian Jay)
|
||||
|
||||
Platform independent, folder-based, and portable tagging system for organizing and searching files. The command line interface and organizing principles are heavily inspired by the todo.txt standard.
|
||||
|
||||
Every file can be assigned projects, contexts, and tags and have a descriptive note.
|
||||
|
||||
Exactly like tasks in todo.txt, files can be categorized by freely defined contexts, defined by the
|
||||
`@` prefix or projects, defined by the `+` prefix. In addition, the `#` prefix defines hashtags that can be assigned.
|
||||
|
||||
So a as an example an audio-file could be assigned to project `+album` and have a context of `@drums` and tagged with `#boombap`, `#lofi`, `#snare`. It's completely up to you how you use the different means of categorization.
|
||||
|
||||
## Command Line Tool
|
||||
|
||||
### Assigning Contextual Tags
|
||||
|
||||
Let's
|
||||
```
|
||||
$ orvani add <file/path> [contextual tags ...]
|
||||
```
|
||||
|
||||
Removing contextual tags from a file
|
||||
```
|
||||
$ orvani remove <file/path> [contextual tags ...]
|
||||
```
|
||||
7
TODO.md
7
TODO.md
|
|
@ -1,4 +1,3 @@
|
|||
+ command line tools
|
||||
+ recursion
|
||||
+ audio player (id3 tags)
|
||||
+ support for markdown tags
|
||||
+ support for textfiles //
|
||||
+ support for Markdown metadata
|
||||
+ support for RST metadata
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
test.txt:
|
||||
contexts: []
|
||||
projects:
|
||||
- test
|
||||
tags:
|
||||
- test
|
||||
98
orvani.py
98
orvani.py
|
|
@ -230,6 +230,35 @@ class OrvaniTag:
|
|||
path = './'
|
||||
if not os.path.dirname(path):
|
||||
path += '/'
|
||||
self.__makeindex(path, recursive, cache)
|
||||
result = self.__search(search, exact)
|
||||
return result
|
||||
|
||||
|
||||
def __intersect(self, result: dict):
|
||||
"""
|
||||
Returns an intersection of two search queries
|
||||
|
||||
result (dict): dict with search result lists to be intersected
|
||||
|
||||
"""
|
||||
mresult = {key: value for key, value in result.items() if value}
|
||||
if len(mresult) < 2:
|
||||
return []
|
||||
common_elements = set(mresult[next(iter(mresult))])
|
||||
for key in mresult.keys():
|
||||
common_elements = common_elements.intersection(mresult[key])
|
||||
return list(common_elements)
|
||||
|
||||
|
||||
def __makeindex(self, path:str, recursive:bool=True, cache: bool=False):
|
||||
"""
|
||||
Creates index for searching, optionally also a cache file
|
||||
|
||||
path (dict): root directory
|
||||
recursive (bool): traverse subdirectories
|
||||
|
||||
"""
|
||||
cachefile = os.path.join(path, self.CACHEFILE)
|
||||
if cache and os.path.isfile(cachefile):
|
||||
try:
|
||||
|
|
@ -251,6 +280,36 @@ class OrvaniTag:
|
|||
yaml.dump(self.INDEX, data)
|
||||
except Exception:
|
||||
print('File write error')
|
||||
|
||||
def __indexfolder(self, sub: str):
|
||||
"""
|
||||
Indexes a folder context
|
||||
|
||||
sub (str): path of folder
|
||||
|
||||
"""
|
||||
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]:
|
||||
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):
|
||||
"""
|
||||
Searches the index and adds search result to it
|
||||
|
||||
search (list): search query list
|
||||
exact (bool): exact match or partial match
|
||||
|
||||
"""
|
||||
result = {
|
||||
'index' : self.INDEX,
|
||||
'found' : []
|
||||
|
|
@ -289,46 +348,9 @@ class OrvaniTag:
|
|||
for sublist in ret.values():
|
||||
min += sublist
|
||||
result['found'] = min
|
||||
return result
|
||||
else:
|
||||
result['found'] = sorted(self.INDEX['files'].keys(), key=lambda x: x.count('/'))
|
||||
return result
|
||||
|
||||
def __intersect(self, result: dict):
|
||||
"""
|
||||
Returns an intersection of two search queries
|
||||
|
||||
result (dict): dict with search result lists to be intersected
|
||||
|
||||
"""
|
||||
mresult = {key: value for key, value in result.items() if value}
|
||||
if len(mresult) < 2:
|
||||
return []
|
||||
common_elements = set(mresult[next(iter(mresult))])
|
||||
for key in mresult.keys():
|
||||
common_elements = common_elements.intersection(mresult[key])
|
||||
return list(common_elements)
|
||||
|
||||
def __indexfolder(self, sub: str):
|
||||
"""
|
||||
Indexes a folder context
|
||||
|
||||
sub (str): path of folder
|
||||
|
||||
"""
|
||||
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]:
|
||||
filelist = [path]
|
||||
if ctx in self.INDEX:
|
||||
if item in self.INDEX[ctx]:
|
||||
filelist += self.INDEX[ctx][item]
|
||||
self.INDEX[ctx][item] = filelist
|
||||
return result
|
||||
|
||||
def mktable(query: str, index: dict):
|
||||
console = Console()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue