diff --git a/README.md b/README.md index 82c8cb814..e3fdd173d 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@

- 《 Hello,算法 》 + 《 Hello 算法 》

@@ -34,7 +34,7 @@ 本项目致力于构建一本开源免费、新手友好的数据结构与算法入门书。 - 全书采用动画图解,结构化地讲解数据结构与算法知识,内容清晰易懂、学习曲线平滑; -- 算法源代码皆可一键运行,现已支持 Java, C++, Python, Go, JS, TS, C#, Swift, Zig 等语言; +- 算法源代码皆可一键运行,支持 Java, C++, Python, Go, JS, TS, C#, Swift, Zig 等语言; - 鼓励读者在章节讨论区互帮互助、共同进步,提问与评论一般能在两日内得到回复; 如果本书对您有所帮助,请点个 Star :star: 支持一下,谢谢! @@ -51,11 +51,11 @@ ## 参与写作 -我们正在加速更新本书,期待您通过提交 Pull Request 来[参与创作](https://www.hello-algo.com/chapter_preface/contribution/),以帮助其他读者获取更优质的学习内容。 +我们正在加速更新本书,期待您通过提交 Pull Request 来[参与本项目](https://www.hello-algo.com/chapter_preface/contribution/),以帮助其他读者获取更优质的学习内容。 -- 如您发现语法错误、内容缺失、文字歧义、无效链接、解释不清晰等问题,烦请帮忙修正或评论指出; -- 期待您参与 C++, Python, Go, JavaScript, TypeScript, C, C#, Swift, Zig, Rust [代码翻译](https://github.com/krahets/hello-algo/issues/15); -- 欢迎您拓展内容或新增章节,若有任何问题请与我联系 WeChat: krahets-jyd ; +- 如您发现语法错误、内容缺失、文字歧义、无效链接、解释不清晰等问题,请帮忙修正或评论指出; +- 期待您参与 C++, Python, Go, JavaScript, TypeScript, C, C#, Swift, Zig, Rust, Dart 等语言[代码翻译](https://github.com/krahets/hello-algo/issues/15); +- 欢迎为您本书内容提出宝贵的意见建议,若有任何问题请提 Issues 或与我联系 WeChat: krahets-jyd ; 感谢本开源书的每一位撰稿人,是他们的无私奉献让这本书变得更好,他们是: diff --git a/docs/chapter_preface/contribution.md b/docs/chapter_preface/contribution.md index 498002c72..90fed8af3 100644 --- a/docs/chapter_preface/contribution.md +++ b/docs/chapter_preface/contribution.md @@ -8,58 +8,44 @@ comments: true 纸质书籍的两次印刷的间隔时间往往需要数年,内容更新非常不方便。
但在本开源 HTML 书中,内容更迭的时间被缩短至数日甚至几个小时。 -由于作者水平有限,书中内容难免疏漏谬误,请您谅解。此外,期待您可以一同参与本书的创作。如果发现笔误、无效链接、内容缺失、文字歧义、解释不清晰、行文结构不合理等问题,烦请您修正内容,以帮助其他读者获取更优质的学习内容。所有 [撰稿人](https://github.com/krahets/hello-algo/graphs/contributors) 将被展示在仓库主页,以感谢您对开源社区的无私奉献。 +由于作者水平有限,书中内容难免疏漏谬误,请您谅解。如果发现笔误、无效链接、内容缺失、文字歧义、解释不清晰、行文结构不合理等问题,请您帮忙修正,以帮助其他读者获取更优质的学习内容。所有[撰稿人](https://github.com/krahets/hello-algo/graphs/contributors)将被展示在仓库与网站主页,以感谢他们对开源社区的无私奉献! -## 修改文字与代码 +## 内容微调 -每个页面的右上角都有一个「编辑」按钮,你可以按照以下步骤修改文章: +每个页面的右上角都有一个「编辑」图标,你可以按照以下步骤修改文字或代码: 1. 点击编辑按钮,如果遇到提示“需要 Fork 此仓库”,请通过; -2. 修改 Markdown 源文件内容; -3. 在页面底部填写更改说明,然后单击“Propose file change”按钮; -4. 页面跳转后,点击“Create pull request”按钮发起拉取请求即可,我会第一时间查看处理并及时更新内容。 +2. 修改 Markdown 源文件内容,并检查内容正确性,尽量保持排版格式统一; +3. 在页面底部填写更改说明,然后单击“Propose file change”按钮;页面跳转后,点击“Create pull request”按钮发起拉取请求即可。 ![edit_markdown](contribution.assets/edit_markdown.png) -## 修改图片与动画 +图片无法直接修改,需要通过新建 [Issue](https://github.com/krahets/hello-algo/issues) 或评论留言来描述图片问题,我会第一时间重新画图并替换图片。 -书中的配图无法直接修改,需要通过以下途径提出修改意见: +## 内容创作 -1. 新建一个 Issue ,将需要修改的图片复制或截图,粘贴在面板中; -2. 描述图片问题,应如何修改; -3. 提交 Issue 即可,我会第一时间重新画图并替换图片。 - -## 创作新内容 - -如果您想要创作新内容,例如 **重写章节、新增章节、修改代码、翻译代码至其他编程语言** 等,那么需要实施 Pull Request 工作流程: +如果您想要参与本开源项目,包括翻译代码至其他编程语言、拓展文章内容等,那么需要实施 Pull Request 工作流程: 1. 登录 GitHub ,并 Fork [本仓库](https://github.com/krahets/hello-algo) 至个人账号; 2. 进入 Fork 仓库网页,使用 `git clone` 克隆该仓库至本地; -3. 在本地进行内容创作(建议通过运行测试来验证代码正确性); +3. 在本地进行内容创作,并通过运行测试来验证代码正确性; 4. 将本地更改 Commit ,并 Push 至远程仓库; -5. 刷新仓库网页,点击“Create pull request”按钮发起拉取请求(Pull Request)即可; - -非常欢迎您和我一同来创作本书! - -## 本地部署 hello-algo - -### Docker +5. 刷新仓库网页,点击“Create pull request”按钮发起拉取请求即可; -请确保 Docker 已经安装并启动,并根据如下命令离线部署。 +## Docker 部署 -稍等片刻,即可使用浏览器打开 `http://localhost:8000` 访问本项目。 +你可以使用 Docker 来部署本项目。 ```bash git clone https://github.com/krahets/hello-algo.git cd hello-algo - docker-compose up -d ``` -使用如下命令即可删除部署。 +稍等片刻,即可使用浏览器打开 `http://localhost:8000` 访问本项目。 + +使用以下命令即可删除部署。 ```bash docker-compose down ``` - -(TODO:教学视频) diff --git a/docs/utils/.gitignore b/docs/utils/.gitignore deleted file mode 100644 index ed8ebf583..000000000 --- a/docs/utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -__pycache__ \ No newline at end of file diff --git a/docs/utils/build_markdown.py b/docs/utils/build_markdown.py deleted file mode 100755 index 92aa59824..000000000 --- a/docs/utils/build_markdown.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -File: build_markdown_docs.py -Created Time: 2023-02-06 -Author: Krahets (krahets@163.com) -""" - -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) - -import re -import glob -import shutil -from docs.utils.number_headings import number_headings -from docs.utils.extract_code_python import ExtractCodeBlocksPython -from docs.utils.extract_code_java import ExtractCodeBlocksJava -from docs.utils.extract_code_cpp import ExtractCodeBlocksCpp -from docs.utils.extract_code_jsts import ExtractCodeBlocksJSTS -from docs.utils.extract_code_swift import ExtractCodeBlocksSwift -from docs.utils.extract_code_csharp import ExtractCodeBlocksCSharp -from docs.utils.extract_code_go import ExtractCodeBlocksGo -from docs.utils.extract_code_zig import ExtractCodeBlocksZig - - -def build_code_blocks(md_path): - with open(md_path, "r") as f: - lines = f.readlines() - - code_blocks_dict = {} - file_pattern = re.compile(r'\s*```(\w+)\s+title="(.+)"') - src_pattern = re.compile(r'\s*\[class\]\{(.*?)\}-\[func\]\{(.*?)\}') - - i = 0 - while i < len(lines): - # Find the line target to the source codes - src_match = src_pattern.match(lines[i]) - if src_match is None: - i += 1 - continue - for j in range(i - 1, -1 ,-1): - file_match = file_pattern.match(lines[j]) - if file_match is not None: - break - # Get the coresponding language code extractor - lang = file_match[1] - file_name = file_match[2] - - if lang not in extractor_dict: - print(f"warning: {lang} is not in the extractor_dict") - i += 1 - continue - - extractor = extractor_dict[lang] - # Get code blocks - if file_name not in code_blocks_dict: - code_blocks = extractor.extract( - file_path=osp.dirname(md_path).replace("docs/", f"codes/{lang}/") + f"/{file_name}") - if code_blocks is None: - i += 1 - continue - code_blocks_dict[file_name] = code_blocks - - header_line = i - class_label = src_match[1] - func_label = src_match[2] - code_blocks = code_blocks_dict[file_name] - - # Add the class to the doc - if not func_label and class_label: - if class_label in code_blocks["classes"]: - lines.pop(header_line) - class_block = code_blocks["classes"][class_label]["block"] - for code_line in class_block[::-1]: - ind = " " * 4 if code_line != "\n" else "" - lines.insert(header_line, ind + code_line) - # Add the function to the doc - elif func_label and not class_label: - if func_label in code_blocks["funcs"]: - lines.pop(header_line) - func_block = code_blocks["funcs"][func_label] - for code_line in func_block["block"][::-1]: - ind = " " * 4 if code_line != "\n" else "" - lines.insert(header_line, ind + code_line) - # Add the class method to the doc - elif func_label and class_label: - if class_label in code_blocks["classes"]: - class_dict = code_blocks["classes"][class_label] - if func_label in class_dict["funcs"]: - lines.pop(header_line) - func_block = class_dict["funcs"][func_label] - for code_line in func_block["block"][::-1]: - lines.insert(header_line, code_line) - - i += 1 - - with open(md_path.replace("docs/", "build/"), "w") as f: - f.writelines(lines) - print(f"Built {md_path}") - - -extractor_dict = { - "java": ExtractCodeBlocksJava(), - "python": ExtractCodeBlocksPython(), - "cpp": ExtractCodeBlocksCpp(), - "go": ExtractCodeBlocksGo(), - "javascript": ExtractCodeBlocksJSTS(), - "typescript": ExtractCodeBlocksJSTS(), - "swift": ExtractCodeBlocksSwift(), - "csharp": ExtractCodeBlocksCSharp(), - "zig": ExtractCodeBlocksZig(), -} - - -if __name__ == "__main__": - # Copy files to the build dir - shutil.copytree("docs", "build", dirs_exist_ok=True) - shutil.rmtree("build/utils") - - # Build code blocks - for md_path in glob.glob("docs/chapter_*/*.md"): - build_code_blocks(md_path) - - # Build headings - number_headings("mkdocs.yml", "build") diff --git a/docs/utils/deploy.sh b/docs/utils/deploy.sh deleted file mode 100644 index 214b75750..000000000 --- a/docs/utils/deploy.sh +++ /dev/null @@ -1,27 +0,0 @@ -python docs/utils/build_markdown.py - -while true; do - read -p "Do you wish to deploy the site? [y] [n]" yn - case $yn in - [Yy]* ) make install; break;; - [Nn]* ) exit;; - * ) echo "Please answer yes[y] or no[n].";; - esac -done - -# push the built docs -cd build -git add . -git commit -m "build" -git push -u origin docs -cd .. - -# Build mkdocs -mkdocs build --clean - -# deploy the site -cd site -git add . -git commit -m "deploy" -git push -u origin gh-pages -cd .. diff --git a/docs/utils/extract_code_cpp.py b/docs/utils/extract_code_cpp.py deleted file mode 100644 index def32ee86..000000000 --- a/docs/utils/extract_code_cpp.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -File: extract_code_cpp.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksCpp(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(static|)\s*(|\S+)\s*(\w+)(\(.*\))\s+\{' - self.class_pattern = r'(public|)\s*(class|struct)\s+(\w+)\s*\{' - - self.func_pattern_keys = ["total", "ind", "static", "return", "label", "args"] - self.class_pattern_keys = ["total", "scope", "type", "label"] - - -# for code_path in glob.glob("codes/cpp/chapter_*/my_heap.cpp"): -# ext = ExtractCodeBlocksCpp() -# ext.extract(code_path) diff --git a/docs/utils/extract_code_csharp.py b/docs/utils/extract_code_csharp.py deleted file mode 100644 index 7a0be0175..000000000 --- a/docs/utils/extract_code_csharp.py +++ /dev/null @@ -1,28 +0,0 @@ -""" -File: extract_code_csharp.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksCSharp(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(public|private|)\s*(static|)\s*(|\S+)\s*(\w+)(\(.*\))' - self.class_pattern = r'(public|)\s*(class|struct)\s+(\w+)\s*\n' - - self.func_pattern_keys = ["total", "ind", "scope", "static", "return", "label", "args"] - self.class_pattern_keys = ["total", "scope", "type", "label"] - -# for code_path in glob.glob("codes/csharp/chapter_*/array.cs"): -# ext = ExtractCodeBlocksCSharp() -# res = ext.extract(code_path) -# pass \ No newline at end of file diff --git a/docs/utils/extract_code_go.py b/docs/utils/extract_code_go.py deleted file mode 100644 index a51450b9e..000000000 --- a/docs/utils/extract_code_go.py +++ /dev/null @@ -1,178 +0,0 @@ -""" -File: extract_code_go.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksGo(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)func\s+(\(.+\))*\s*(\w+)\((.*)\)\s*(\S*)\s*{\n' - self.class_pattern = r'(\s*)type\s+(\w+)' - - self.func_pattern_keys = ["total", "ind", "class", "label", "params", "return"] - self.class_pattern_keys = ["total", "ind", "label"] - - def extract(self, file_path): - """ - Extract classes and functions from a markdown document - """ - if not osp.isfile(file_path): - return None - - self.file_path = file_path - with open(file_path) as f: - self.lines = f.readlines() - self.content = "".join(self.lines) - - # Detect and extract all the classes and fucntions - classes = self.extract_class_blocks() - funcs = self.extract_function_blocks(classes=classes) - - self.post_process(classes, funcs) - - return { - "classes": classes, - "funcs": funcs, - } - - def extract_function_blocks(self, classes=None, class_label="", indentation=0): - """ - Extract all the functions with given indentation - """ - - funcs = {} - func_pattern = re.compile(self.func_pattern) - - for line_num in range(len(self.lines)): - # Search the function header - func_match = func_pattern.match(self.lines[line_num]) - if func_match is None: - continue - header_line = line_num - - func_label = func_match.group(self.func_pattern_keys.index("label")) - func_cls_label = func_match.group(self.func_pattern_keys.index("class")) - func_return = func_match.group(self.func_pattern_keys.index("return")) - - def check_func_blong_to_class(label): - class_label_pattern = re.compile(f".*\*{label}\).*") - func_return_pattern = re.compile(f".*{label}.*") - constructor_pattern = re.compile(f".*new.*") - - class_label_match = class_label_pattern.match(f"{func_cls_label}") - func_return_match = func_return_pattern.match(f"{func_return}") - constructor_match = constructor_pattern.match(func_label) - - return class_label_match, func_return_match, constructor_match - - if classes: - # The function should not blong to any class - flag = False - for label in classes: - # Match the target class label - class_label_match, func_return_match, constructor_match = \ - check_func_blong_to_class(label) - - if class_label_match is not None or \ - func_return_match is not None and constructor_match is not None: - flag = True - if flag: - continue - - elif class_label: - # Match the target class label - class_label_match, func_return_match, constructor_match = \ - check_func_blong_to_class(class_label) - - if class_label_match is None and func_return_match is None or \ - func_return_match is not None and constructor_match is None: - continue - - # Search the block from the header line - start_line, end_line, func_block = self.search_block( - header_line, indentation) - # Construct the funcs dict - funcs[func_label] = { - "indentation": indentation, - "line_number": { - "start": start_line, - "end": end_line, - "header": header_line, - }, - "block": func_block, - } - - return funcs - - def extract_class_blocks(self): - """ - Extract all the classes with given indentation - """ - classes = {} - class_pattern = re.compile(self.class_pattern) - - for line_num, line in enumerate(self.lines): - # Search the class header - class_match = class_pattern.match(line) - if class_match is None: - continue - header_line = line_num - - # Search the block from the header line - _, _, class_block = self.search_block( - header_line, 0) - # Construct the classes dict - class_label = class_match.group(self.class_pattern_keys.index("label")) - funcs = self.extract_function_blocks(class_label=class_label) - # Merge function blocks to class_block - for func in funcs.values(): - class_block.append('\n') - class_block += func["block"] - - classes[class_label] = { - "indentation": 0, - "line_number": { - "header": header_line, - }, - "block": class_block, - "funcs": funcs, - } - - return classes - - def post_process(self, classes, funcs): - """ - Process the classes and functions - """ - def replace_tabs(x): - for i, line in enumerate(x["block"]): - x["block"][i] = line.replace("\t"," " * self.ind) - - def add_inds(x): - for i, line in enumerate(x["block"]): - if line != "\n": - x["block"][i] = " " * self.ind + line - - for clas in classes.values(): - replace_tabs(clas) - for func in clas["funcs"].values(): - replace_tabs(func) - add_inds(func) - for func in funcs.values(): - replace_tabs(func) - - -for code_path in glob.glob("codes/*/chapter_*/graph_adjacency_matrix.go"): - ext = ExtractCodeBlocksGo() - res = ext.extract(code_path) - pass diff --git a/docs/utils/extract_code_java.py b/docs/utils/extract_code_java.py deleted file mode 100644 index 699bcc42d..000000000 --- a/docs/utils/extract_code_java.py +++ /dev/null @@ -1,168 +0,0 @@ -""" -File: extract_code_java.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) - - -class ExtractCodeBlocksJava: - def __init__(self) -> None: - self.ind = 4 - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(public|private|)\s*(static|)\s*(\S+)\s+(\w+)(\(.*\))\s+\{' - self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{' - - self.func_pattern_keys = ["total", "ind", "scope", "static", "return", "label", "args"] - self.class_pattern_keys = ["total", "scope", "label"] - - # Pattern to match the start and end of a block - self.block_start_pattern = '^\s{ind}\/\*.+\*\/' - self.block_end_pattern = '^\s{ind}\}' - self.block_start_shift = 0 - self.block_end_shift = 0 - - def extract(self, file_path): - """ - Extract classes and functions from a markdown document - """ - if not osp.isfile(file_path): - return None - - self.file_path = file_path - with open(file_path) as f: - self.lines = f.readlines() - self.content = "".join(self.lines) - - # Detect and extract all the classes and fucntions - classes = self.extract_class_blocks() - funcs = self.extract_function_blocks() - - self.post_process(classes, funcs) - - return { - "classes": classes, - "funcs": funcs, - } - - def search_block(self, header_line, indentation): - """ - Search class/function block given the header_line and indentation - """ - start_line, end_line = 0, len(self.lines) - - block_end_pattern = re.compile( - self.block_end_pattern.replace("ind", str(indentation))) - block_start_pattern = re.compile( - self.block_start_pattern.replace("ind", str(indentation))) - - # Search the code - for i in range(header_line + 1, len(self.lines)): - if re.match(block_end_pattern, self.lines[i]) is not None: - end_line = i + self.block_end_shift - break - # Search the header comment - for i in range(header_line - 1, -1, -1): - if re.search(block_start_pattern, self.lines[i]) is not None: - start_line = i + self.block_start_shift - break - - return start_line, end_line, self.lines[start_line:end_line + 1] - - def extract_function_blocks(self, indentation=0, start_line=-1, end_line=-1): - """ - Extract all the functions with given indentation - """ - funcs = {} - - if start_line == -1: - start_line = 0 - if end_line == -1: - end_line = len(self.lines) - 1 - - func_pattern = re.compile(self.func_pattern) - - for line_num in range(start_line, end_line + 1): - # Search the function header - func_match = func_pattern.match(self.lines[line_num]) - if func_match is None: - continue - # The function should match the input indentation - if len(func_match.group(self.func_pattern_keys.index("ind"))) != indentation: - continue - header_line = line_num - - # Search the block from the header line - start_line, end_line, func_block = self.search_block( - header_line, indentation) - # Construct the funcs dict - func_label = func_match.group(self.func_pattern_keys.index("label")) - funcs[func_label] = { - "indentation": indentation, - "line_number": { - "start": start_line, - "end": end_line, - "header": header_line, - }, - "block": func_block, - } - - return funcs - - def extract_class_blocks(self): - """ - Extract all the classes with given indentation - """ - classes = {} - class_pattern = re.compile(self.class_pattern) - - for line_num, line in enumerate(self.lines): - # Search the class header - class_match = class_pattern.match(line) - if class_match is None: - continue - header_line = line_num - - # Search the block from the header line - start_line, end_line, class_block = self.search_block( - header_line, 0) - # Construct the classes dict - class_label = class_match.group(self.class_pattern_keys.index("label")) - classes[class_label] = { - "indentation": 0, - "line_number": { - "start": start_line, - "end": end_line, - "header": header_line, - }, - "block": class_block, - "funcs": self.extract_function_blocks( - indentation=self.ind, start_line=start_line, end_line=end_line) - } - - return classes - - def post_process(self, classes, funcs): - """ - Process the classes and functions - """ - def remove_keyword(func): - block = func["block"] - header_line = func["line_number"]["header"] - \ - func["line_number"]["start"] - block[header_line] = block[header_line] \ - .replace("static ", "", 1).replace("public ", "", 1).replace("private ", "", 1) - for clas in classes.values(): - remove_keyword(clas) - for func in clas["funcs"].values(): - remove_keyword(func) - for func in funcs.values(): - remove_keyword(func) - -# ext = ExtractCodeBlocksJava() -# ext.extract("codes/java/chapter_array_and_linkedlist/my_list.java") diff --git a/docs/utils/extract_code_jsts.py b/docs/utils/extract_code_jsts.py deleted file mode 100644 index 86568149c..000000000 --- a/docs/utils/extract_code_jsts.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -File: extract_code_jsts.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksJSTS(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(function|private|public|)\s*(\S*)\(.*\)(:|)\s*(.*)\s+{\s*\n' - self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{' - - self.func_pattern_keys = ["total", "ind", "prefix", "label", ":", "return"] - self.class_pattern_keys = ["total", "scope", "label"] diff --git a/docs/utils/extract_code_python.py b/docs/utils/extract_code_python.py deleted file mode 100755 index e2f32c7ed..000000000 --- a/docs/utils/extract_code_python.py +++ /dev/null @@ -1,51 +0,0 @@ -""" -File: extract_code_python.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksPython(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)def\s+(\w+)\s*\(' - self.class_pattern = r'class\s+(\w+)' - - self.func_pattern_keys = ["total", "ind", "label"] - self.class_pattern_keys = ["total", "label"] - - # Pattern to match the start and end of a block - self.block_end_pattern = '^\s{0,ind}\S+.*\n' - self.block_start_pattern = '^\s{ind}""".+' - self.block_start_shift = 0 - self.block_end_shift = -1 - - def post_process(self, classes, funcs): - """ - Process the classes and functions - """ - def remove_empty_lines(func): - start_line, end_line = func["line_number"]["start"], func["line_number"]["end"] - block = func["block"] - # Remove empty lines at bottom - for i in range(len(block) - 1, -1, -1): - if re.search("^\s*\n", block[i]) is None: - break - end_line -= 1 - func["line_number"]["end"] = end_line - func["block"] = block[:end_line - start_line + 1] - - for clas in classes.values(): - remove_empty_lines(clas) - for func in clas["funcs"].values(): - remove_empty_lines(func) - for func in funcs.values(): - remove_empty_lines(func) diff --git a/docs/utils/extract_code_swift.py b/docs/utils/extract_code_swift.py deleted file mode 100644 index 565935231..000000000 --- a/docs/utils/extract_code_swift.py +++ /dev/null @@ -1,23 +0,0 @@ -""" -File: extract_code_swift.py -Created Time: 2023-02-08 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksSwift(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(public|private|)\s*(static|)\s*(func|)\s*(\w+)\(.*\).+{\s*\n' - self.class_pattern = r'(public|)\s*class\s+(\w+)\s*\{' - - self.func_pattern_keys = ["total", "ind", "scope", "static", "func", "label"] - self.class_pattern_keys = ["total", "scope", "label"] diff --git a/docs/utils/extract_code_zig.py b/docs/utils/extract_code_zig.py deleted file mode 100644 index 6de189b3a..000000000 --- a/docs/utils/extract_code_zig.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -File: extract_code_zig.py -Created Time: 2023-02-07 -Author: Krahets (krahets@163.com) -""" - -import re -import glob -import sys, os.path as osp -sys.path.append(osp.dirname(osp.dirname(osp.dirname(osp.abspath(__file__))))) -from docs.utils.extract_code_java import ExtractCodeBlocksJava - - -class ExtractCodeBlocksZig(ExtractCodeBlocksJava): - def __init__(self) -> None: - super().__init__() - - self.ind = 4 - - # Pattern to match function names and class names - self.func_pattern = r'(\s*)(pub|)\s*fn\s+(\w+)\(.+\)\s*(.+)\s*{\n' - self.class_pattern = r'(\s*)(pub|)\s*(fn|const)\s+(\w+)\(*.+\)*\s*(type|struct)\s*{\n' - - self.func_pattern_keys = ["total", "ind", "scope", "label", "return"] - self.class_pattern_keys = ["total", "ind", "scope", "type", "label", "struct"] - - # Pattern to match the start and end of a block - self.block_start_pattern = '^\s*\n' - self.block_start_shift = 1 - - def extract_class_blocks(self): - """ - Extract all the classes with given indentation - """ - classes = {} - class_pattern = re.compile(self.class_pattern) - - for line_num, line in enumerate(self.lines): - # Search the class header - class_match = class_pattern.match(line) - if class_match is None: - continue - header_line = line_num - - # Search the block from the header line - start_line, end_line, class_block = self.search_block( - header_line, 0) - # Construct the classes dict - class_label = class_match.group(self.class_pattern_keys.index("label")) - # Define the indentation by the class type - class_type = class_match.group(self.class_pattern_keys.index("type")) - self.ind = 8 if class_type == "fn" else 4 - classes[class_label] = { - "indentation": 0, - "line_number": { - "start": start_line, - "end": end_line, - "header": header_line, - }, - "block": class_block, - "funcs": self.extract_function_blocks( - indentation=self.ind, start_line=start_line, end_line=end_line) - } - - return classes - - def post_process(self, classes, funcs): - """ - Process the classes and functions - """ - def remove_keyword(func): - block = func["block"] - header_line = func["line_number"]["header"] - \ - func["line_number"]["start"] - block[header_line] = block[header_line].replace("pub ", "", 1) - - for clas in classes.values(): - remove_keyword(clas) - for func in clas["funcs"].values(): - remove_keyword(func) - if func["indentation"] == 8: - for i, line in enumerate(func["block"]): - func["block"][i] = line[4:] - for func in funcs.values(): - remove_keyword(func) - -# for code_path in glob.glob("codes/*/chapter_*/my_heap.zig"): -# ext = ExtractCodeBlocksZig() -# res = ext.extract(code_path) -# pass \ No newline at end of file diff --git a/docs/utils/number_headings.py b/docs/utils/number_headings.py deleted file mode 100755 index cf45c9b10..000000000 --- a/docs/utils/number_headings.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -File: number_headings.py -Created Time: 2023-02-16 -Author: Krahets (krahets@163.com) -""" - -import re - -def get_heading_info_from_nav(mkdocs_path): - """ - Get heading info from mkdocs navigation - """ - - with open(mkdocs_path) as f: - lines = f.readlines()[125:] - # Get nav lines - for i, line in enumerate(lines): - if "nav:" in line: - break - lines = lines[i:] - - # Search articles - articles = [] - for line in lines: - level = 0 - level_re = None - while level_re is None and level < 3: - level += 1 - level_pat = level * " " - level_pat = f"^{level_pat}- \d" - level_re = re.search(level_pat, line) - # Only add articles with heading level 2 - if level != 2: - continue - - number_pat = level * "\d+." - number_re = re.search(number_pat, line) - number = re.search(number_pat, line).group(0) if number_re else None - file_path = re.search("\S+\/\S+\.md", line).group(0) - - article = { - "level": level, - "number": number, - "file_path": file_path - } - articles.append(article) - - print(f"{file_path}, heading number is {number}") - - return articles - -def number_article(article, base_dir="build"): - """ - Number a doc - """ - - with open(f"{base_dir}/{article['file_path']}", "r") as f: - lines = f.readlines() - - # Add h1, h2 heading numbers - h2_count = 1 - for i, line in enumerate(lines): - h1_re = re.search("^(#)\s+\S+", line) - if h1_re is not None: - h1 = h1_re.group(1) - lines[i] = line.replace(h1, f"# {article['number']}") - continue - - h2_re = re.search("^(##)\s+\S+", line) - if h2_re is not None: - h2 = h2_re.group(1) - lines[i] = line.replace(h2, f"## {article['number']}{h2_count}.") - h2_count += 1 - - with open(f"{base_dir}/{article['file_path']}", "w") as f: - f.writelines(lines) - - -def number_headings(mkdocs_path, build_dir): - """ - Build headings - """ - - articles = get_heading_info_from_nav(mkdocs_path) - - for article in articles: - number_article(article, base_dir=build_dir)