aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Peter McGoron 2021-07-25 11:33:43 -0400
committerGravatar - 2021-07-26 22:55:41 -0400
commit633cf0fcd438ad0dfb05cfaf7f7127b525d8c52f (patch)
tree130025d8687ad233200ebd727368a10d11fc623d
parentadd inspect_tagmap.md (diff)
underwriter: start new argument parser
-rw-r--r--example/natargs.md2
-rw-r--r--example/natargs_python_impl.md34
-rw-r--r--natargs.py59
-rwxr-xr-xunderwriter47
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)