Add params and conditions for template
This commit is contained in:
parent
77ba4c758d
commit
01bf72155c
5 changed files with 121 additions and 15 deletions
|
@ -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()
|
||||
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
41
ictmpl/param.py
Normal 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
|
Reference in a new issue