mirror of
ssh://git.janware.com/srv/git/janware/proj/jw-python
synced 2026-01-15 09:53:32 +01:00
process-text-files.py: Implement command indent-cpp-macros
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
parent
6dd594d47b
commit
a676ff5cdf
1 changed files with 106 additions and 0 deletions
|
|
@ -78,6 +78,84 @@ class Cmd(jwutils.Cmd):
|
|||
return data
|
||||
return r
|
||||
|
||||
@staticmethod
|
||||
def _indent_cpp_macros(data, src, target, context=None):
|
||||
|
||||
def __ctx(context, key, default):
|
||||
if key in context:
|
||||
return context[key]
|
||||
return default
|
||||
|
||||
def format_line(context, indent, directive, rhs):
|
||||
if indent < 0:
|
||||
indent = 0
|
||||
spaces = __ctx(context, 'spaces', 2)
|
||||
indent_macro = __ctx(context, 'indent-macro', 0)
|
||||
indent_def = __ctx(context, 'indent-definiton', 40)
|
||||
indent_comment = __ctx(context, 'indent-comment', 70)
|
||||
rhs = rhs.strip()
|
||||
directive = directive.strip()
|
||||
r = '#' + ' ' * indent * spaces + directive
|
||||
if len(rhs) == 0:
|
||||
return r + '\n'
|
||||
r += ' '
|
||||
if indent_macro > 1:
|
||||
r = r.ljust(indent_macro - 1)
|
||||
if not directive in [ 'define' ]:
|
||||
return (r + rhs).rstrip() + '\n'
|
||||
#slog(NOTICE, "dissecting", rhs)
|
||||
m = re.match("^\s*(\w+(\([^)]*\))*)(\s+(.*))*", rhs)
|
||||
if m is None:
|
||||
raise Exception("invalid rhs", rhs)
|
||||
macro = m.group(1)
|
||||
def_and_comment = m.group(4)
|
||||
#slog(NOTICE, "macro=>{}<, def+comment=>{}<".format(macro, def_and_comment))
|
||||
r += macro
|
||||
if def_and_comment is None:
|
||||
return r.rstrip() + '\n'
|
||||
r += ' '
|
||||
if indent_def > 1:
|
||||
r = r.ljust(indent_def - 1)
|
||||
parts = re.split("(//|/\*)", def_and_comment)
|
||||
if len(parts) <= 1:
|
||||
return r + def_and_comment + '\n'
|
||||
if len(parts) == 2:
|
||||
raise Exception("Failed to dissect definition + comment", def_and_comment)
|
||||
return (r + parts[0].strip()).ljust(indent_comment) + parts[1].strip() + ' ' + ''.join(parts[2:]).strip() + '\n'
|
||||
|
||||
skip_outer = True
|
||||
if context is not None:
|
||||
if 'skip-outer' in context:
|
||||
skip_outer = context['skip-outer']
|
||||
r = ''
|
||||
lnum = 0
|
||||
level = -1 if context['skip-outer'] else 0
|
||||
lines = data.splitlines()
|
||||
for line in iter(lines):
|
||||
lnum += 1
|
||||
m = re.match("^\s*#\s*(\w+)(\W*)(.*)", line)
|
||||
if m is None:
|
||||
r += line + '\n'
|
||||
continue
|
||||
directive = m.group(1)
|
||||
rhs = (m.group(2) + m.group(3)).strip()
|
||||
#slog(NOTICE, "{}: directive=>{}<, rhs=>{}<".format(level, directive, rhs))
|
||||
if directive is None or rhs is None:
|
||||
raise Exception("Syntax error in line", lnum, ":", line)
|
||||
if directive in [ "if", "ifdef", "ifndef" ]:
|
||||
r += format_line(context, level, directive, rhs)
|
||||
level += 1
|
||||
continue
|
||||
if directive in [ "else" ]:
|
||||
r += format_line(context, level - 1, directive, rhs)
|
||||
continue
|
||||
if directive in [ "endif" ]:
|
||||
level -= 1
|
||||
r += format_line(context, level, directive, rhs)
|
||||
continue
|
||||
r += format_line(context, level, directive, rhs)
|
||||
return r
|
||||
|
||||
@staticmethod
|
||||
def _cleanup_spaces(data, src, target, context=None):
|
||||
lines = data.splitlines()
|
||||
|
|
@ -346,6 +424,34 @@ class CmdIndentMakefileEquals(Cmd):
|
|||
if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context):
|
||||
slog(NOTICE, "+ aligned equals :", path)
|
||||
|
||||
class CmdIndentCppMacros(Cmd):
|
||||
|
||||
def __init__(self):
|
||||
super(CmdIndentCppMacros, self).__init__("indent-cpp-macros", "Indent and beautify C/C++ preprocessor macros")
|
||||
|
||||
def add_parser(self, parsers):
|
||||
p = super(CmdIndentCppMacros, self).add_parser(parsers)
|
||||
p.add_argument('-w', "--spaces", help="Number of spaces per indentation level", type=int, default=2)
|
||||
p.add_argument('-s', "--skip-outer", help="Skip the outmost macro (read multiple-inclusion guards)", action='store_true', default=True)
|
||||
p.add_argument('-S', "--skip-outer-name-regex", help="Regex for file names that --skip-outer should be applied to", default="\.h$|\.H$|\.hpp$")
|
||||
return p
|
||||
|
||||
def process(self, args, files):
|
||||
slog(NOTICE, "Beautifying", len(files), "C++ files:")
|
||||
context = dict()
|
||||
context["spaces"] = args.spaces
|
||||
replacements = {"blah": "blub"} # just a dummy to use _replace_in_file, TODO: obviate the need
|
||||
for dir, name in files:
|
||||
path = dir + '/' + name
|
||||
if self._replace_in_file(path, replacements, func=self._cleanup_spaces):
|
||||
slog(NOTICE, "+ purged spaces :", path)
|
||||
if args.skip_outer and re.search(args.skip_outer_name_regex, path):
|
||||
context["skip-outer"] = True
|
||||
else:
|
||||
context["skip-outer"] = False
|
||||
if self._replace_in_file(path, replacements, func=self._indent_cpp_macros, context=context):
|
||||
slog(NOTICE, "+ indented C++ macros :", path)
|
||||
|
||||
class CmdCleanupSpaces(Cmd):
|
||||
|
||||
def __init__(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue