自动生成C++头文件的定义检测语句

工作中总是要写头文件的 #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基类中,做了递归操作,将文件类型过滤出来,方便后期脚本的拓展

另外用于分析是否定义,这里使用的是相同接口,方案可以通过继承来拓展

猜你喜欢

转载自blog.csdn.net/qq_23880193/article/details/79111694