工作中总是要写头文件的 #ifndef ... #endif 比较烦,写了脚本,批量添加
(代码为了可以方便拓展,代码结构需要耐心分析),对于只要功能的小伙伴,直接拿去运行就可以了
import sys
import os
import shutil
import re
import chardet
class IFileClassify(object):
def file_h(self, filename):
pass
def file_cpp(self, filename):
pass
class CFileIteration(IFileClassify):
def __init__(self, root_name):
self.m_root = root_name
def __get_file_type(self, filename):
list_tmp = filename.split('.')
if len(list_tmp) < 2:
return None
return list_tmp[-1]
def __find_dir(self, root):
# 检测根目录是否是目录
if os.path.isdir(root):
# 获取文件列表
dir_list = os.listdir(root)
for path in dir_list:
full_path = root + "/" + path
self.__find_dir(full_path)
# 处理目录
# self.__find_dir(root)
elif os.path.isfile(root):
# 处理文件
self.__handle_file(root)
def __handle_file(self, filename):
str_file_type = self.__get_file_type(filename)
if str_file_type is None:
return
if str_file_type == "h":
self.file_h(filename)
elif str_file_type == "cpp":
self.file_cpp(filename)
def find(self):
self.__find_dir(self.m_root)
class IFilterDefine(object):
def filter(self, content, define_name):
pass
class CReFilterDefine(IFilterDefine):
def filter(self, content, define_name):
is_define = re.match(r"#ifndef %s.*#endif" % define_name, r'' + content)
if is_define is not None:
return True
else:
return False
class CIsExistFilterDefine(IFilterDefine):
def filter(self, content, define_name):
print("#ifndef %s" % define_name)
if ("#ifndef %s" % define_name) in content and "#endif" in content:
return True
else:
return False
class CAlreayDefineException(Exception):
pass
class CAddDefineForHFile(CFileIteration):
def __init__(self, root_name):
super(CAddDefineForHFile, self).__init__(root_name)
# self.m_filter = CReFilterDefine()
self.m_filter = CIsExistFilterDefine()
def file_h(self, filename):
tmp_file_name = filename + ".bak"
# 拷贝一份源文件
shutil.copyfile(filename, tmp_file_name)
src_fp = None
dst_fp = None
try:
# 打开文件
src_fp = open(tmp_file_name, "r", encoding="utf-8")
dst_fp = open(filename, "w+", encoding="utf-7")
# 读取整个文件,判断是否存在#ifndef...#endif
full_text = src_fp.read()
src_fp.seek(0)
# 获取定义名称
name, ext = os.path.splitext(os.path.basename(filename))
upper_name = name.upper()
define_name = "__" + upper_name + "_H__"
is_define = self.m_filter.filter(full_text, define_name)
if is_define is True:
raise CAlreayDefineException()
# 在文件的头部插入define
dst_fp.write("#ifndef " + define_name + "\n")
dst_fp.write("#define " + define_name + "\n\n")
while True:
line = src_fp.readline()
if line == "":
break
dst_fp.write(line)
# 在文件的结尾插入#endif
dst_fp.write("\n\n#endif // " + define_name + "\n")
except CAlreayDefineException:
# 还原
shutil.copyfile(tmp_file_name, filename)
except UnicodeDecodeError:
shutil.copyfile(tmp_file_name, filename)
except Exception as e:
print(e)
finally:
if src_fp is not None:
src_fp.close()
if dst_fp is not None:
dst_fp.close()
# 删除临时文件
os.remove(tmp_file_name)
def arg_select():
# 获取参数列表
arg_list = sys.argv
if len(arg_list) == 1:
# 打印帮助信息
print("please input root dir name\n\texample: ./file")
return
dir_name = arg_list[1]
add_define_h_file = CAddDefineForHFile(dir_name)
add_define_h_file.find()
def main():
arg_select()
if __name__ == "__main__":
main()
find基类中,做了递归操作,将文件类型过滤出来,方便后期脚本的拓展
另外用于分析是否定义,这里使用的是相同接口,方案可以通过继承来拓展