Skip to content

Instantly share code, notes, and snippets.

@ericgj
Last active May 9, 2018 16:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ericgj/6ef970a3504467abdea9f1e414c37dd3 to your computer and use it in GitHub Desktop.
Save ericgj/6ef970a3504467abdea9f1e414c37dd3 to your computer and use it in GitHub Desktop.
#!/bin/env python
import sys
import re
from argparse import ArgumentParser
WORD_SPLIT = re.compile('[^a-zA-Z0-9]+')
FIRST_ALPHA = re.compile('^[a-zA-Z]')
def render(args,typename,values):
return u'\n'.join(
module_decl(typename, namespace=args.namespace) +
[u''] +
imports_decl() +
[u''] +
type_decl(typename,values) +
[u''] +
list_decl(typename,values) +
[u''] +
to_string_decl(typename,values) +
[u''] +
from_string_decl(typename,values) +
[u''] +
decode_decl(typename) +
[u''] +
encode_decl(typename) +
[u'']
)
def module_decl(typename,namespace=None):
if namespace is None:
return [ u'module %s exposing (..)' % (typename.as_string()) ]
else:
return [ u'module %s.%s exposing (..)' % (namespace,typename.as_string()) ]
def imports_decl():
return (
[ u'import Json.Decode as JD',
u'import Json.Encode as JE'
]
)
def type_decl(typename,values):
return (
[ u'type %s' % (typename.as_string()) ] +
[ u' = %s' % (v.name()) if i == 0 else
u' | %s' % (v.name()) for (i,v) in enumerate(values)
]
)
def list_decl(typename,values):
return (
[ u'list : List %s' % (typename.as_string()) ,
u'list ='
] +
[ u' [ %s' % (v.name()) if i == 0 else
u' , %s' % (v.name()) for (i,v) in enumerate(values)
] +
[ u' ]']
)
def to_string_decl(typename,values):
return (
[ u'toString : %s -> String' % (typename.as_string()) ,
u'toString %s =' % (typename.arg_name())
] +
[ u' case %s of' % (typename.arg_name()) ] +
[ (u' %s ->\n' +
u' "%s"') % (v.name(), v.as_string()) for v in values
]
)
def from_string_decl(typename,values):
return (
[ u'fromString : String -> Maybe %s' % (typename.as_string()) ,
u'fromString s ='
] +
[ u' case s of' ] +
[ (u' "%s" ->\n' +
u' Just %s') % (v.as_string(), v.name()) for v in values
] +
[ u' _ ->',
u' Nothing'
]
)
def decode_decl(typename):
return (
[ u'decode : JD.Decoder %s' % (typename.as_string()) ,
u'decode =',
u' JD.string',
u' |> JD.andThen (\str ->',
u' fromString str',
u' |> Maybe.map JD.succeed',
u' |> Maybe.withDefault (JD.fail "Unknown %s: \' + str + \'")' % (typename.as_string(),) ,
u' )'
]
)
def encode_decl(typename):
return (
[ u'encode : %s -> JE.Value' % (typename.as_string()) ,
u'encode value =',
u' JE.string <| toString value'
]
)
def titlecase(s):
if len(s) == 0:
return s
else:
return s[0].upper() + s[1:].lower()
def first_alpha_or_prefix(prefix,s):
if len(s) == 0:
return s
else:
if FIRST_ALPHA.search(s):
return s
else:
return prefix + s
class TypeName():
def __init__(self,s):
self.value = s
def name(self):
return u''.join(
titlecase( first_alpha_or_prefix(u'Type',s) ) if i == 0 else titlecase(s)
for (i,s) in enumerate( re.split(WORD_SPLIT,self.value) )
)
def arg_name(self):
return u''.join(
first_alpha_or_prefix(u'type',s).lower() if i == 0 else titlecase(s)
for (i,s) in enumerate( re.split(WORD_SPLIT,self.value) )
)
def as_string(self):
return self.value
pgm = ArgumentParser(description=u"Generate Elm module for enum (value type)")
pgm.add_argument(u'tname', metavar=u'TYPE', type=TypeName, help=u'Type name')
pgm.add_argument(u'--namespace', metavar=u'NS', help=u'Module namespace' )
args = pgm.parse_args()
typename = args.tname
values = [ TypeName(v.strip()) for v in sys.stdin.read().strip().split(u'\n') ]
sys.stdout.write( render(args, typename, values) )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment