1
0
mirror of https://gitlab.gnome.org/GNOME/nautilus synced 2024-06-30 23:46:35 +00:00
nautilus/data/lineup-parameters
Ondrej Holy 7b469dfa87 ci: Use lineup-parameters python script
The lineup-parameters.c is hard to use with meson. Let's use the python
rewrite from
https://gitlab.gnome.org/GNOME/epiphany/-/blob/master/data/lineup-parameters
instead.
2021-10-11 06:45:26 +00:00

211 lines
6.7 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Copyright © 2019 Michael Catanzaro <mcatanzaro@gnome.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Based on original C lineup-parameters by Sébastien Wilmet <swilmet@gnome.org>
# Rewritten in Python to allow simple execution from source directory.
#
# Usage: lineup-parameters [file]
# If the file is not given, stdin is read.
# The result is printed to stdout.
#
# The restrictions:
# - The function name must be at column 0, followed by a space and an opening
# parenthesis;
# - One parameter per line;
# - A parameter must follow certain rules (see the regex in the code), but it
# doesn't accept all possibilities of the C language.
# - The opening curly brace ("{") of the function must also be at column 0.
#
# If one restriction is missing, the function declaration is not modified.
#
# Example:
#
# gboolean
# frobnitz (Frobnitz *frobnitz,
# gint magic_number,
# GError **error)
# {
# ...
# }
#
# Becomes:
#
# gboolean
# frobnitz (Frobnitz *frobnitz,
# gint magic_number,
# GError **error)
# {
# ...
# }
#
# TODO: support "..." vararg parameter
import argparse
import re
import sys
from typing import NamedTuple
# https://regexr.com/ is your friend.
functionNameRegex = re.compile(r'^(\w+) ?\(')
parameterRegex = re.compile(
r'^\s*(?P<type>(const\s+)?\w+)'
r'\s+(?P<stars>\**)'
r'\s*(?P<name>\w+)'
r'\s*(?P<end>,|\))'
r'\s*$')
openingCurlyBraceRegex = re.compile(r'^{\s*$')
def matchFunctionName(line):
match = functionNameRegex.match(line)
if match:
functionName = match.group(1)
firstParamPosition = match.end(0)
return (functionName, firstParamPosition)
return (None, 0)
class ParameterInfo(NamedTuple):
paramType: str
name: str
numStars: int
isLastParameter: bool
def matchParameter(line):
_, firstParamPosition = matchFunctionName(line)
match = parameterRegex.match(line[firstParamPosition:])
if match is None:
return None
paramType = match.group('type')
assert(paramType is not None)
name = match.group('name')
assert(name is not None)
stars = match.group('stars')
numStars = len(stars) if stars is not None else 0
end = match.group('end')
isLastParameter = True if end is not None and end == ')' else False
return ParameterInfo(paramType, name, numStars, isLastParameter)
def matchOpeningCurlyBrace(line):
return True if openingCurlyBraceRegex.match(line) is not None else False
# Length returned is number of lines the declaration takes up
def getFunctionDeclarationLength(remainingLines):
for i in range(len(remainingLines)):
currentLine = remainingLines[i]
parameterInfo = matchParameter(currentLine)
if parameterInfo is None:
return 0
if parameterInfo.isLastParameter:
if i + 1 == len(remainingLines):
return 0
nextLine = remainingLines[i + 1]
if not matchOpeningCurlyBrace(nextLine):
return 0
return i + 1
return 0
def getParameterInfos(remainingLines, length):
parameterInfos = []
for i in range(length):
parameterInfos.append(matchParameter(remainingLines[i]))
return parameterInfos
def computeSpacing(parameterInfos):
maxTypeLength = 0
maxStarsLength = 0
for parameterInfo in parameterInfos:
maxTypeLength = max(maxTypeLength, len(parameterInfo.paramType))
maxStarsLength = max(maxStarsLength, parameterInfo.numStars)
return (maxTypeLength, maxStarsLength)
def printParameter(parameterInfo, maxTypeLength, maxStarsLength, outfile):
outfile.write(f'{parameterInfo.paramType:<{maxTypeLength + 1}}')
paramNamePaddedWithStars = f'{parameterInfo.name:*>{parameterInfo.numStars + len(parameterInfo.name)}}'
outfile.write(f'{paramNamePaddedWithStars:>{maxStarsLength + len(parameterInfo.name)}}')
def printFunctionDeclaration(remainingLines, length, useTabs, outfile):
functionName, _ = matchFunctionName(remainingLines[0])
assert(functionName is not None)
outfile.write(f'{functionName} (')
numSpacesToParenthesis = len(functionName) + 2
whitespace = ''
if useTabs:
tabs = ''.ljust(numSpacesToParenthesis // 8, '\t')
spaces = ''.ljust(numSpacesToParenthesis % 8)
whitespace = tabs + spaces
else:
whitespace = ''.ljust(numSpacesToParenthesis)
parameterInfos = getParameterInfos(remainingLines, length)
maxTypeLength, maxStarsLength = computeSpacing(parameterInfos)
numParameters = len(parameterInfos)
for i in range(numParameters):
parameterInfo = parameterInfos[i]
if i != 0:
outfile.write(whitespace)
printParameter(parameterInfo, maxTypeLength, maxStarsLength, outfile)
if i + 1 != numParameters:
outfile.write(',\n')
outfile.write(')\n')
def parseContents(infile, useTabs, outfile):
lines = infile.readlines()
i = 0
while i < len(lines):
line = lines[i]
functionName, _ = matchFunctionName(line)
if functionName is None:
outfile.write(line)
i += 1
continue
remainingLines = lines[i:]
length = getFunctionDeclarationLength(remainingLines)
if length == 0:
outfile.write(line)
i += 1
continue
printFunctionDeclaration(remainingLines, length, useTabs, outfile)
i += length
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description='Line up parameters of C functions')
parser.add_argument('infile', nargs='?',
type=argparse.FileType('r'),
default=sys.stdin,
help='input C source file')
parser.add_argument('-o', metavar='outfile', nargs='?',
type=argparse.FileType('w'),
default=sys.stdout,
help='where to output modified file')
parser.add_argument('--tabs', action='store_true',
help='whether use tab characters in the output')
args = parser.parse_args()
parseContents(args.infile, args.tabs, args.o)
args.infile.close()
args.o.close()