diff options
| author | 2021-07-25 11:33:43 -0400 | |
|---|---|---|
| committer | 2021-07-26 22:55:41 -0400 | |
| commit | 633cf0fcd438ad0dfb05cfaf7f7127b525d8c52f (patch) | |
| tree | 130025d8687ad233200ebd727368a10d11fc623d | |
| parent | add inspect_tagmap.md (diff) | |
underwriter: start new argument parser
| -rw-r--r-- | example/natargs.md | 2 | ||||
| -rw-r--r-- | example/natargs_python_impl.md | 34 | ||||
| -rw-r--r-- | natargs.py | 59 | ||||
| -rwxr-xr-x | underwriter | 47 |
4 files changed, 110 insertions, 32 deletions
diff --git a/example/natargs.md b/example/natargs.md new file mode 100644 index 0000000..b9963e7 --- /dev/null +++ b/example/natargs.md @@ -0,0 +1,2 @@ +Natural arguments are those like git commands `git commit`, `git stash`, +etc. They are "natural" since they are arranged like an english sentence. diff --git a/example/natargs_python_impl.md b/example/natargs_python_impl.md new file mode 100644 index 0000000..e80d09a --- /dev/null +++ b/example/natargs_python_impl.md @@ -0,0 +1,34 @@ +The arguments are stored as a trie using python dictonaries. Each node +is a class consisting of two functions and a dict representing a subtree. + +One function is a check on the length of the arguments, and the other +is the function executed on the list of arguments. + +pseudocode +---------- + +``` +def addargs(dict, h::[], chk, f): + if dict[h] exists: + throw exception + dict[h].chk = chk + dict[h].f = f + dict[h].subtree = {} +def addargs(dict, h::t, chk, f): + if dict[h] does not exist: + dict[h].chk = None + dict[h].f = None + dict[h].subtree = addargs(dict[h].subtree, t, chk, f) + +def execargs(dict, h::t): + if dict[h] exists: + f,args = execargs(dict[h].subtree, t) + if f,args is None,None: + if not dict[h].chk(t): + return None,None + return dict[h].f,t + else: + return f,args + else: + return None,None +``` diff --git a/natargs.py b/natargs.py new file mode 100644 index 0000000..8e96d2c --- /dev/null +++ b/natargs.py @@ -0,0 +1,59 @@ +########################################################################### +# +########################################################################### + +class DuplicateArgumentException: + def __str__(self): + return f"{self.oldargs} already exists" + def __init__(self, oldargs): + self.oldargs = oldargs + +class TrieElem: + def dochk(self, l): + return True if self.chk is None \ + else self.chk(len(l)) + + def __init__(self, chk, f, st): + self.chk = chk + self.f = f + self.st = st + +def addargs(dic, oldargs, args, chk, f): + if len(args) == 1: + if args[0] in dic: + raise DuplicateArgumentException(oldargs) + else: + dic[args[0]] = TrieElem(chk,f,{}) + else: + if args[0] not in dic: + dic[args[0]] = TrieElem(None, None, {}) + dic[args[0]].st = addargs(dic[args[0]].st, \ + oldargs, args[1:], chk, f) + return dic + +def getarg(dict, l): + if len(l) == 0 or l[0] not in dict: + return None + else: + resolved = getarg(dict[l[0]].st, l[1:]) + if resolved is None: + return dict[l[0]].f,l[1:] \ + if dict[l[0]].dochk(l[1:]) \ + else None + else: + return resolved + +class Arguments: + def execarg(self, args): + res = getarg(self.trie, args) + if res is None: + raise Exception + return res[0](res[1]) + + def addarg(self, args, chk, f): + if args == []: + raise ValueError + self.trie = addargs(self.trie, args, args, chk, f) + + def __init__(self): + self.trie = {} diff --git a/underwriter b/underwriter index 960cee4..8b42c8f 100755 --- a/underwriter +++ b/underwriter @@ -5,6 +5,7 @@ import os.path import sys from datetime import datetime, timezone import base64 +from natargs import Arguments def current_time(): return int(datetime.now(timezone.utc).timestamp()) @@ -80,16 +81,21 @@ END; def make_cursor(self): return self.db.cursor(Cursor) - def card_add_tags(self, name, tags): + def card_add_tags(self, args): cur = self.make_cursor() + name = args[0] + tags = args[1:] + cur.new_card(name) cur.new_tags(tags) cur.add_tags_to_cards([(name,t) for t in tags]) self.db.commit() - def card_remove_tags(self, name, tags): + def card_remove_tags(self, args): cur = self.make_cursor() - cur.remove_tags_from_cards([(name,t) for t in tags]) + cur.remove_tags_from_cards( + [(args[0],t) for t in args[1:]] + ) self.db.commit() def remove_card(self, name): @@ -178,33 +184,10 @@ if __name__ == "__main__": args = args[2:] ctx = Context(db) + argparse = Arguments() + argparse.addarg(["tag"], lambda x:x > 0, ctx.card_add_tags) + argparse.addarg(["untag"], lambda x:x > 0, ctx.card_remove_tags) + argparse.addarg(["list", "tags"], lambda x: x > 0, ctx.tags_for_cards) + argparse.addarg(["list", "cards"], lambda x: x > 0, ctx.cards_for_tags) - if len(args) == 0: - usage() - sys.exit(0) - if args[0] == "tag": - ctx.card_add_tags(args[1], args[2:]) - elif args[0] == "remove": - for i in args[1:]: - ctx.remove(i) - elif args[0] == "untag": - ctx.card_remove_tags(args[1], args[2:]) - elif args[0] == "list": - if len(args) < 3: - usage() - sys.exit(1) - if args[1] == "tags": - ctx.tags_for_cards(args[2:]) - elif args[1] == "cards": - ctx.cards_for_tags(args[2:]) - else: - usage() - sys.exit(1) - elif args[0] == "rename": - if len(args) != 3: - usage() - sys.exit(1) - ctx.rename_card(args[1], args[2]) - else: - usage() - sys.exit(1) + argparse.execarg(args) |
