From 42c9cbf002576b893fa19ad8be0bafaacfd0850c Mon Sep 17 00:00:00 2001 From: randogoth Date: Tue, 6 Jun 2023 22:14:10 +0300 Subject: [PATCH] modularized list method --- .context.yaml | 4 +- README.md | 26 +++++++++++++ TODO.md | 7 ++-- dir/.context.yaml | 6 --- dir/test.txt | 0 orvani.py | 98 +++++++++++++++++++++++++++++------------------ test/file.md | 0 7 files changed, 90 insertions(+), 51 deletions(-) create mode 100644 README.md delete mode 100644 dir/.context.yaml delete mode 100644 dir/test.txt delete mode 100644 test/file.md diff --git a/.context.yaml b/.context.yaml index d04d595..4b8e464 100644 --- a/.context.yaml +++ b/.context.yaml @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..4da9783 --- /dev/null +++ b/README.md @@ -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 [contextual tags ...] +``` + +Removing contextual tags from a file +``` +$ orvani remove [contextual tags ...] +``` \ No newline at end of file diff --git a/TODO.md b/TODO.md index 17228a2..b7b5ec9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,4 +1,3 @@ -+ command line tools -+ recursion -+ audio player (id3 tags) -+ support for markdown tags \ No newline at end of file ++ support for textfiles // ++ support for Markdown metadata ++ support for RST metadata \ No newline at end of file diff --git a/dir/.context.yaml b/dir/.context.yaml deleted file mode 100644 index cb4cca5..0000000 --- a/dir/.context.yaml +++ /dev/null @@ -1,6 +0,0 @@ -test.txt: - contexts: [] - projects: - - test - tags: - - test diff --git a/dir/test.txt b/dir/test.txt deleted file mode 100644 index e69de29..0000000 diff --git a/orvani.py b/orvani.py index 6ea51aa..3e77844 100644 --- a/orvani.py +++ b/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() diff --git a/test/file.md b/test/file.md deleted file mode 100644 index e69de29..0000000