将 Allman 风格的括号改为 Stroustrup 风格






4.89/5 (2投票s)
用于更改自动生成的代码的括号风格的程序。
引言
change_to_stroustrup_style.py 程序是一个非常简单的程序,用于更改完全使用 Allman 括号风格编写的代码的括号风格。代码非常简单,*不是*一个通用的美化程序。所做的只是将与空格位于同一行的开括号移动到前一行末尾,并在空格后添加一个空格字符。
该程序对于其预期目的非常有用。我在 codeproject 上发布了三个 C 或 C++ 代码生成器,它们都使用 Allman 括号风格编写代码。这是我首选的风格,但我意识到并非每个人都喜欢它。
Allman 风格的一个例子是
if (a == b) { c = a; } else { d = a; }
即使 Allman 风格不是我首选的风格,我仍然会编写代码生成器以输出该风格,因为该风格的括号始终位于单独的一行上,因此对于将代码转换为其他风格的程序来说,无需进行复杂的解析。
change_to_stroustrup_style.py 程序将 Allman 风格代码文件的风格更改为 Stroustrup 风格的括号。如果将上面的代码更改为 Stroustrup 风格,它将变为
if (a == b) { c = a; } else { d = a; }
该程序仅对格式正确的 Allman 风格程序有效。
该程序还提供了一个使用 Python 生成器的简单示例。
使用代码
命令格式如下
python change_to_stroustrup_style.py <file_name> [-b]
-b 选项或 --backup 选项可用于用户希望保存原始文件备份的情况。
代码
在 Python 中,使用简单的 'for' 循环迭代文件中的所有行很常见,如下所示
for line in input_file: # Code to process the string 'line' goes here. <code omitted>
对于这种情况,需要在代码的下一行添加开括号到前一行末尾,使用 Python 生成器获取文件的每一行比使用简单的循环需要更复杂的代码。
因此,此代码利用了 Python 生成器功能。以下函数从任何可迭代项生成一个生成器。该函数返回一个生成器实例。'yield' 语句在调用返回实例的 'next' 方法时返回下一个 item
。当返回最终项目时,再次调用 'next' 方法会引发 StopIteration 类型的异常。
def get_iterable_item_generator(iterable_instance): """ Create a generator that provides one iterable item at a time. """ for item in iterable_instance: yield item
程序
#!/usr/bin/env python #======================================================================= # Copyright (C) 2013 William Hallahan # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. #======================================================================= """ python change_to_stroustrup_style.py <file_name> [-b] Change bracketing style of an Allman-style C program to Stroustrup-style bracketing. For example: if (a == b) { c = a; } else { d = a; } becomes: if (a == b) { c = a; } else { d = a; } """ import sys import os from shutil import copyfile from argparse import ArgumentParser def get_iterable_item_generator(iterable_instance): """ Create a generator that provides one iterable item at a time. """ for item in iterable_instance: yield item def execute_change_to_stroustrup_style(input_file_name, backup): """ Convert Allman-style to Stroustrup-style. """ # Make a copy of the file. backup_file_name = 'backup_{0}'.format(input_file_name) copyfile(input_file_name, backup_file_name) # Read the copied file and write to a new file with the original # file name. with open(input_file_name, 'w') as outfile: with open(backup_file_name) as infile: line_generator = get_iterable_item_generator(infile) line = '' try: line = line_generator.next().strip('\n') while True: next_line = line_generator.next() while next_line.strip() == '{': line = '{0} {1}'.format(line, '{') next_line = line_generator.next() outfile.write('{0}\n'.format(line)) line = next_line.strip('\n') except StopIteration: pass outfile.write('{0}\n'.format(line)) # Optionally delete the copy of the original file. if not backup: os.remove(backup_file_name) return 0 # Start of main program. def main(argv=None): # Initialize the command line parser. parser = ArgumentParser(description='The program converts C or C++ code formatted in Allman-style to Strousop-style.', epilog='Copyright (c) 2013 William Hallahan - All Rights Reserved.', add_help=True, argument_default=None, # Global argument default usage=__doc__) parser.add_argument(action='store', dest='input_file_name', help='Print the help information.') parser.add_argument('-b', '--backup', action='store_true', dest='backup', default=False, help='Save a backup of the original file.') # Parse the command line. arguments = parser.parse_args(args=argv) input_file_name = arguments.input_file_name backup = arguments.backup status = 0 try: execute_change_to_stroustrup_style(input_file_name, backup) except ValueError as value_error: print value_error status = -1 except EnvironmentError as environment_error: print environment_error status = -1 return status if __name__ == "__main__": sys.exit(main())
关注点
该程序可以轻松修改为编写 K&R 风格。K&R 风格与 Stroustrup 风格不同地格式化 'if' 语句的 'else' 子句。对于前面的示例,K&R 风格是
if (a == b) { c = a; } else { d = a; }
顺便说一下,我总是添加开括号和闭括号,即使它们不需要,如上面的示例所示。这使得代码更易于维护。企业发现,代码的成本通常有 85% 用于维护,因此易于维护通常比其他考虑因素更重要。
历史
- 初始发布。