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 data
|
||||||
return r
|
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
|
@staticmethod
|
||||||
def _cleanup_spaces(data, src, target, context=None):
|
def _cleanup_spaces(data, src, target, context=None):
|
||||||
lines = data.splitlines()
|
lines = data.splitlines()
|
||||||
|
|
@ -346,6 +424,34 @@ class CmdIndentMakefileEquals(Cmd):
|
||||||
if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context):
|
if self._replace_in_file(path, replacements, func=self._indent_pattern, context=context):
|
||||||
slog(NOTICE, "+ aligned equals :", path)
|
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):
|
class CmdCleanupSpaces(Cmd):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue