Add params and conditions for template

This commit is contained in:
Dmitriy Pleshevskiy 2018-06-11 07:37:28 +03:00
parent 77ba4c758d
commit 01bf72155c
5 changed files with 121 additions and 15 deletions

View File

@ -1,10 +1,11 @@
from .config import Config
from .ictmpl import Ictmpl
from .param import Param
ictmpl = Ictmpl(Config())
__all__ = ('Param', )
if __name__ == '__main__':
from .config import Config
from .ictmpl import Ictmpl
ictmpl = Ictmpl(Config())
ictmpl.run()

View File

@ -3,8 +3,8 @@
__title__ = 'ictmpl'
__description__ = 'Generate projects from templates'
__url__ = 'https://github.com/ideascup/ictmpl/'
__version__ = '1.0.0'
__build__ = 0x010000
__version__ = '1.1.0'
__build__ = 0x010100
__author__ = 'Dmitriy Pleshevskiy'
__author_email__ = 'dmitriy@ideascup.me'
__license__ = 'MIT'

View File

@ -1,5 +1,6 @@
import os
from re import compile, sub
import json
from re import compile, sub, _pattern_type
from os.path import abspath, isdir, join
from shutil import copytree, rmtree
@ -9,6 +10,8 @@ __all__ = ('parse_ignore_file', 'copytree_with_ignore', 'treewalk')
RE_DOUBLESTAR = compile(r'\*\*')
RE_STAR = compile(r'\*')
RE_IF_CONDITION = compile(r'\s*%\s*(endif|if\s+(.+))\s*%')
def parse_ignore_file(filepath):
regexes = []
@ -94,8 +97,45 @@ def replace_template_file(filepath, app):
params = app.params
with open(filepath, 'r') as file:
filedata = file.read()
for key, value in params.items():
filedata = sub(r'%%{}%%'.format(key), value, filedata)
# replace conditions
cut_info = None
cond_deep = 0
start_index = 0
while True:
match = RE_IF_CONDITION.search(filedata[start_index:])
if not match:
break
start, end = [start_index+v for v in match.span()]
statement = match.group(1)
if statement.startswith('if '):
cond_deep += 1
local = params.copy()
exec('result__=bool({})'.format(match.group(2)), local)
if local['result__']:
filedata = filedata[:start] + filedata[end:]
start_index = start
elif cut_info is None:
cut_info = (start, cond_deep)
start_index = end
else:
if cut_info is not None \
and cut_info[1] is cond_deep:
start = cut_info[0]
cut_info = None
filedata = filedata[:start] + filedata[end:]
start_index = start
# replace params
for key, value in params.items():
if isinstance(value, _pattern_type):
continue
elif value is None or isinstance(value, bool):
value = str(value)
else:
value = json.dumps(value)
filedata = sub(r'%%{}%%'.format(key), value, filedata)
with open(filepath, 'w') as file:
file.write(filedata)

View File

@ -7,6 +7,7 @@ from uuid import uuid4
from textwrap import dedent
from shutil import rmtree
from ictmpl import Param
from ictmpl.helpers.git import Git
from ictmpl.helpers.fsutil import (
copytree_with_ignore, rmtree_without_ignore, replace_template_file)
@ -21,6 +22,28 @@ RE_GITLINK = compile(r'^(?:git@|https?://)')
RE_COMMAND_ENV = compile(r'#!(.+)')
def ask_params(app, params=None, deep=0):
if not params:
return
for param in params:
if not isinstance(param, Param):
if isinstance(param, (list, tuple)):
app.params[param[0]] = param[1]
continue
while True:
value = input(' '*deep*4 + param.question) or param.default
try:
param_value = param.strparse(value)
app.params[param.name] = param_value
if param.children and param_value:
ask_params(app, param.children, deep=deep+1)
break
except Exception as e:
print(e)
def create_project(args, app):
project_path = abspath(args.path)
@ -47,7 +70,8 @@ def create_project(args, app):
try:
with open('.ictmplrc', 'r') as file:
exec(file.read(), rc)
except:
except Exception as e:
print(e)
return
dependencies = rc.get('sysDependencies', None)
@ -68,12 +92,11 @@ def create_project(args, app):
'author_website', 'licence'):
app.params['__{}__'.format(key.upper())] = rc.get(key, '')
params = rc.get('params', {})
params = rc.get('params', [])
if params:
print('Configure template:')
for param, default in params.items():
question = 'SET {}: ({}) '.format(param, default)
app.params[param] = input(question) or default
ask_params(app, params)
print(app.params)
print('------------------\n')
print('Walking files and replace params')
@ -81,6 +104,7 @@ def create_project(args, app):
if templates:
templates = map(lambda p: join(project_path, p), templates)
for filepath in templates:
print(filepath)
replace_template_file(filepath, app)
else:
for root, dirs, files in os.walk(project_path):
@ -108,6 +132,6 @@ def create_project(args, app):
proc.communicate()
except KeyboardInterrupt:
proc.kill()
rmtree(project_path)
# rmtree(project_path)
finally:
os.remove(tmpfilename)

41
ictmpl/param.py Normal file
View File

@ -0,0 +1,41 @@
class Param:
def __init__(self, name, default, vtype=None, question=None, children=None):
self.name = name
self.default = default
self.vtype = vtype or type(default)
if not question:
question = 'SET {0}: ({1})'
try:
question = question.format(name, self.format(default))
except:
pass
self.question = question + ' '
self.children = children
def strparse(self, value):
if self.vtype is not str and type(value) is self.vtype:
return value
if self.vtype in (list, tuple) \
or (self.vtype is str and ',' in value):
return [v.strip() for v in value.split(',') if v.strip()]
elif self.vtype is bool:
return value[:1].lower() == 'y'
return self.vtype(value)
def format(self, value):
type_ = type(value)
if type_ in (list, tuple):
value = ', '.join(value)
elif type_ is bool:
nvindex = int(not value)
value = '/'.join(
v.upper() if nvindex is i else v
for i, v in enumerate('yn'))
return value