Commit accf6566 authored by Ryan Pavlik's avatar Ryan Pavlik

Initial, functioning version

parent 6f704d91
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018 Collabora, Ltd.
#
# SPDX-License-Identifier: BSL-1.0
#
# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com>
#
# Purpose: Generates a .cpp and .h file with the given stem,
# containing the expected default/boilerplate contents
import argparse
import file_boilerplate.filters
from jinja2 import Environment, FileSystemLoader
from jinja2.utils import Markup
from uuid import uuid4
from re import sub
from sys import exit
import subprocess
from datetime import date
from os import getcwd
from os.path import exists
def make_guid_include_guard(fn):
guid = str(uuid4()).upper().replace('-','_')
raw_include_guard = "INCLUDED_{fn}_GUID_{guid}".format(fn=fn, guid=guid)
# Try to make a valid C preprocessor identifier:
# Convert "bad" characters to _
return sub(r"[-./]", '_', raw_include_guard)
def make_author():
return '{name} <{email}>'.format(
name=subprocess.getoutput('git config user.name'),
email=subprocess.getoutput('git config user.email'))
def make_year():
return date.today().year
def do_make_guid():
return str(uuid4()).upper()
def make_environment():
env = Environment(keep_trailing_newline=True, autoescape=False, loader=FileSystemLoader([getcwd() + '/.boilerplate']))
env.globals['year'] = make_year()
env.globals['author'] = make_author()
env.filters['prefix_block'] = file_boilerplate.filters.do_prefix_block
env.filters['make_identifier'] = file_boilerplate.filters.do_make_identifier
env.globals['make_guid'] = do_make_guid
env.filters['c_block_comment'] = file_boilerplate.filters.do_c_block_comment
return env
class BoilerplateOutput(object):
def __init__(self, fn, data):
self.fn = fn
self.data = data
def __str__(self):
return '\n'.join(['Filename: ' + self.fn, 'Contents:', self.data])
def write(self, force=False):
if exists(self.fn):
if force:
print("Overwriting {} ...".format(self.fn))
else:
print('Error: {} already exists (and not forcing)! Not overwriting...'.format(self.fn))
return False
else:
print("Generating {} ...".format(self.fn))
# Write the output
with open(self.fn, 'w', encoding='utf-8') as f:
f.write(self.data)
return True
class BoilerplateRun(object):
def __init__(self):
self.env = make_environment()
def get_env(self):
return self.env.overlay()
def render(self, stem, ext):
env = self.get_env()
template = env.get_template('template.%s' % ext, globals=dict(stem=stem))
output = template.render(year=make_year(), author=make_author())
fn = template.module.fn()
return BoilerplateOutput(fn=fn, data=output)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('stem', metavar='stem', nargs='?',
help='Specify generated filename stem (.cpp and .h will be added)')
parser.add_argument('--noh', action='store_true', default=False,
help='Skip generating the .h file')
parser.add_argument('--nocpp', action='store_true', default=False,
help='Skip generating the .cpp file')
parser.add_argument('-f', '--force', action='store_true', default=False,
help='Write file(s) even if already existing')
args = parser.parse_args()
success = True
run = BoilerplateRun()
if not args.noh:
success = run.render(stem=args.stem,
ext="h").write(force=args.force) and success
if not args.nocpp:
success = run.render(ext='cpp',
stem=args.stem).write(force=args.force) and success
if success:
exit()
exit(-1)
\ No newline at end of file
#!/usr/bin/env python3 -i
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018 Collabora, Ltd.
#
# SPDX-License-Identifier: BSL-1.0
#
# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com>
#
# Purpose: Filters useful in generating source code boilerplate
def do_prefix_block(s, line_prefix, block_begin=None, block_end=None, blank_line_prefix=None):
"""Prefix each line of a block of text with a string, as well as applying a begin and end block string.
Can specify the prefix to be different on blank lines, e.g. to avoid trailing space.
Mostly for commenting a block of text as appropriate for the language.
"""
# Inspired by Jinja2's 'indent' filter
if blank_line_prefix is None:
# Nothing passed for blank line prefix
blank_line_prefix = line_prefix.strip()
newline = u'\n'
s += newline # this quirk is necessary for splitlines method
def filter_line(l):
if l:
return line_prefix + l
return blank_line_prefix + l
lines = s.splitlines()
# If there's a trailing LF, we must remove it so it doesn't look like a blank line
# We re-add it after filtering the lines.
trailingLF = False
if lines and not lines[-1]:
trailingLF = True
lines = lines[:-1]
lines = list(map(filter_line, lines))
if trailingLF:
lines.append('')
if block_begin is not None:
if lines:
lines[0] = block_begin + lines[0]
else:
lines[0] = block_begin
if block_end is not None:
if lines:
lines[-1] = lines[-1] + block_end
else:
lines[0] = block_end
return newline.join(lines)
def do_make_identifier(s, replacement='_'):
"""Transform characters that aren't valid in identifiers to the given alternate character."""
from re import sub
return sub(r"[-/. \n]", replacement, s)
def do_c_block_comment(s, begin_chars, line_prefix, end_chars):
return do_prefix_block(s, line_prefix=line_prefix, blank_line_prefix=line_prefix.rstrip(),
block_begin=(begin_chars + '\n'), block_end=('\n' + end_chars))
\ No newline at end of file
# -*- coding: utf-8 -*-
#
# Copyright (c) 2018 Collabora, Ltd.
#
# SPDX-License-Identifier: BSL-1.0
#
# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com>
from file_boilerplate.filters import *
from nose.tools import eq_
def test_do_prefix_block_no_newline():
eq_(do_prefix_block('A', line_prefix='prefix'),('prefixA'))
eq_(do_prefix_block('A', line_prefix='prefix', block_begin='BEGIN'),('BEGINprefixA'))
eq_(do_prefix_block('A', line_prefix='prefix', block_end='END'),('prefixAEND'))
eq_(do_prefix_block('A', line_prefix='prefix', block_begin='BEGIN', block_end='END'),('BEGINprefixAEND'))
def test_do_prefix_block_two_full_lines():
eq_(do_prefix_block('A\nB', line_prefix='prefix'),
('prefixA\nprefixB'))
eq_(do_prefix_block('A\nB', line_prefix='prefix', block_begin='BEGIN'),
('BEGINprefixA\nprefixB'))
eq_(do_prefix_block('A\nB', line_prefix='prefix', block_end='END'),
('prefixA\nprefixBEND'))
eq_(do_prefix_block('A\nB', line_prefix='prefix', block_begin='BEGIN', block_end='END'),
('BEGINprefixA\nprefixBEND'))
# Specifying blank line prefix here shouldn't affect output
eq_(do_prefix_block('A\nB', line_prefix='prefix', block_begin='BEGIN', block_end='END', blank_line_prefix='blank'),('BEGINprefixA\nprefixBEND'))
def test_do_prefix_block_one_line_with_lf():
eq_(do_prefix_block('A\n', line_prefix='prefix'),('prefixA\n'))
eq_(do_prefix_block('A\n', line_prefix='prefix', block_begin='BEGIN'),('BEGINprefixA\n'))
eq_(do_prefix_block('A\n', line_prefix='prefix', block_end='END'),('prefixA\nEND'))
eq_(do_prefix_block('A\n', line_prefix='prefix', block_begin='BEGIN', block_end='END'),('BEGINprefixA\nEND'))
# Specifying blank line prefix here shouldn't affect output
eq_(do_prefix_block('A\n', line_prefix='prefix', block_begin='BEGIN', block_end='END', blank_line_prefix='blank'),
('BEGINprefixA\nEND'))
def test_do_prefix_block_two_full_lines_with_lf():
eq_(do_prefix_block('A\nB\n', line_prefix='prefix'),
('prefixA\nprefixB\n'))
eq_(do_prefix_block('A\nB\n', line_prefix='prefix', block_begin='BEGIN'),
('BEGINprefixA\nprefixB\n'))
eq_(do_prefix_block('A\nB\n', line_prefix='prefix', block_end='END'),
('prefixA\nprefixB\nEND'))
eq_(do_prefix_block('A\nB\n', line_prefix='prefix', block_begin='BEGIN', block_end='END'),
('BEGINprefixA\nprefixB\nEND'))
# Specifying blank line prefix here shouldn't affect output
eq_(do_prefix_block('A\nB\n', line_prefix='prefix', block_begin='BEGIN', block_end='END', blank_line_prefix='blank'),
('BEGINprefixA\nprefixB\nEND'))
def test_do_prefix_block_full_blank_full():
eq_(do_prefix_block('A\n\nB\n', line_prefix='prefix'),
('prefixA\nprefix\nprefixB\n'))
eq_(do_prefix_block('A\n\nB\n', line_prefix='prefix', block_begin='BEGIN'),
('BEGINprefixA\nprefix\nprefixB\n'))
eq_(do_prefix_block('A\n\nB\n', line_prefix='prefix', block_end='END'),
('prefixA\nprefix\nprefixB\nEND'))
eq_(do_prefix_block('A\n\nB\n', line_prefix='prefix', block_begin='BEGIN', block_end='END'),
('BEGINprefixA\nprefix\nprefixB\nEND'))
# Specifying blank line prefix here should change middle line
eq_(do_prefix_block('A\n\nB\n', line_prefix='prefix', block_begin='BEGIN', block_end='END', blank_line_prefix='blank'),
('BEGINprefixA\nblank\nprefixB\nEND'))
intext = """Copyright (c) 2018 Collabora, Ltd.
SPDX-License-Identifier: Apache-2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License."""
expected = """
/*
** Copyright (c) 2018 Collabora, Ltd.
**
** SPDX-License-Identifier: Apache-2.0
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
** http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/
"""
def test_real_text():
assert do_prefix_block(intext, line_prefix='** ', blank_line_prefix='**', block_begin='/*\n', block_end='\n*/') == expected
def test_identifier():
eq_(do_make_identifier('asdf'), 'asdf')
eq_(do_make_identifier('as-df'), 'as_df')
eq_(do_make_identifier('as/df'), 'as_df')
eq_(do_make_identifier('as.df'), 'as_df')
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment