mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 21:25:31 +00:00
Update docs
This commit is contained in:
parent
4b08fd21a2
commit
cbaf48c04b
13 changed files with 164 additions and 32 deletions
|
@ -6,7 +6,7 @@ Beginners should read the instructions [here](https://github.com/erg-lang/erg/is
|
||||||
|
|
||||||
## Documents
|
## Documents
|
||||||
|
|
||||||
If you are thinking of contributing to Erg, you should read documents under `doc/*/dev_guide`. In particular, please pre-install what is written in `env.md`.
|
If you are thinking of contributing to Erg, you should read documents under `doc/*/dev_guide`. In particular, please pre-install what is written in [`env.md`](doc/EN/dev_guide/env.md).
|
||||||
|
|
||||||
Or you are interested in the internal structure of Erg, `doc/*/compiler` may provide useful information.
|
Or you are interested in the internal structure of Erg, `doc/*/compiler` may provide useful information.
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
## ドキュメント
|
## ドキュメント
|
||||||
|
|
||||||
Erg への貢献を考えている場合は、`doc/*/dev_guide` にあるドキュメントを読む必要があります。特に`env.md`に書かれているものを事前にインストールしてください。
|
Erg への貢献を考えている場合は、`doc/*/dev_guide` にあるドキュメントを読む必要があります。特に[`env.md`](../JA/dev_guide/env.md)に書かれているものを事前にインストールしてください。
|
||||||
|
|
||||||
Erg の内部構造に興味がある場合は、`doc/*/compiler` が役に立つかもしれません。
|
Erg の内部構造に興味がある場合は、`doc/*/compiler` が役に立つかもしれません。
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ Ergのバグだと思われる動作を見つけた場合は、[報告](https://
|
||||||
|
|
||||||
私たちは常に、ドキュメントをさまざまな言語バージョンに翻訳してくれる人を探しています。
|
私たちは常に、ドキュメントをさまざまな言語バージョンに翻訳してくれる人を探しています。
|
||||||
|
|
||||||
ドキュメントが他の言語に比べて古くなっていることに気づき、内容を更新したいという方も歓迎します ([こちら](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362) を参照)。これを行う方法について)。
|
ドキュメントが他の言語に比べて古くなっていることに気づき、内容を更新したいという方も歓迎します (これを行う方法については[こちら](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362) を参照)。
|
||||||
|
|
||||||
## 質問する
|
## 質問する
|
||||||
|
|
||||||
ご不明な点がございましたら、[Discord チャンネル](https://discord.gg/zfAAUbgGr4)までお気軽にお問い合わせください。
|
ご不明な点がございましたら、[Discord チャンネル](https://discord.gg/zfAAUbgGr4)でお気軽にお問い合わせください。
|
||||||
|
|
||||||
## 開発・実装に関して
|
## 開発・実装に関して
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Architecture of `ergc`
|
# Architecture of `ergc`
|
||||||
|
|
||||||
## 1. Scan an Erg script (.er) and generate a `TokenStream` (parser/lex.rs)
|
## 1. Scan an Erg script (.er) and generate a `TokenStream`
|
||||||
|
|
||||||
|
src: [erg_parser\lex.rs](../../../crates/erg_parser/lex.rs)
|
||||||
|
|
||||||
* parser/lexer/Lexer generates `TokenStream` (this is an iterator of `Token`, `TokenStream` can be generated by `Lexer::collect()`)
|
* parser/lexer/Lexer generates `TokenStream` (this is an iterator of `Token`, `TokenStream` can be generated by `Lexer::collect()`)
|
||||||
* `Lexer` is constructed from `Lexer::new` or `Lexer::from_str`, where `Lexer::new` reads the code from a file or command option.
|
* `Lexer` is constructed from `Lexer::new` or `Lexer::from_str`, where `Lexer::new` reads the code from a file or command option.
|
||||||
|
@ -9,21 +11,42 @@
|
||||||
* `LexerRunner` can also be used if you want to use `Lexer` as standalone; `Lexer` is just an iterator and does not implement the `Runnable` trait.
|
* `LexerRunner` can also be used if you want to use `Lexer` as standalone; `Lexer` is just an iterator and does not implement the `Runnable` trait.
|
||||||
* `Runnable` is implemented by `LexerRunner`, `ParserRunner`, `Compiler`, and `DummyVM`.
|
* `Runnable` is implemented by `LexerRunner`, `ParserRunner`, `Compiler`, and `DummyVM`.
|
||||||
|
|
||||||
## 2. Convert `TokenStream` -> `AST` (parser/parse.rs)
|
## 2. Convert `TokenStream` -> `AST`
|
||||||
|
|
||||||
|
src: [erg_parser\parse.rs](../../../crates/erg_parser/parse.rs)
|
||||||
|
|
||||||
* `Parser`, like `Lexer`, has two constructors, `Parser::new` and `Parser::from_str`, and `Parser::parse` will give the `AST`.
|
* `Parser`, like `Lexer`, has two constructors, `Parser::new` and `Parser::from_str`, and `Parser::parse` will give the `AST`.
|
||||||
* `AST` is the wrapper type of `Vec<Expr>`. It is for "Abstract Syntax Tree".
|
* `AST` is the wrapper type of `Vec<Expr>`. It is for "Abstract Syntax Tree".
|
||||||
|
|
||||||
### 2.1 Desugaring `AST`
|
### 2.1 Desugaring `AST`
|
||||||
|
|
||||||
|
src: [erg_parser/desugar.rs](../../../crates/erg_parser/desugar.rs)
|
||||||
|
|
||||||
* expand nested vars (`Desugarer::desugar_nest_vars_pattern`)
|
* expand nested vars (`Desugarer::desugar_nest_vars_pattern`)
|
||||||
* desugar multiple pattern definition syntax (`Desugarer::desugar_multiple_pattern_def`)
|
* desugar multiple pattern definition syntax (`Desugarer::desugar_multiple_pattern_def`)
|
||||||
|
|
||||||
### 2.2 Reordering & Linking `AST`
|
### 2.2 Reordering & Linking `AST`
|
||||||
|
|
||||||
* Sort variables according to dependencies and link class methods to class definitions (`Linker::link`)
|
src: [erg_compiler/reorder.rs](../../../crates/erg_compiler/reorder.rs)
|
||||||
|
|
||||||
## 3. Type checking & inference, Convert `AST` -> `HIR` (compiler/lower.rs)
|
* link class methods to class definitions
|
||||||
|
* method definitions are allowed outside of the class definition file
|
||||||
|
* current implementation is incomplete, only in the same file
|
||||||
|
|
||||||
|
## 3. Convert `AST` -> `HIR`
|
||||||
|
|
||||||
|
(main) src: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs)
|
||||||
|
|
||||||
|
## 3.1 Name Resolution
|
||||||
|
|
||||||
|
In the current implementation it is done during type checking.
|
||||||
|
|
||||||
|
* All ASTs (including imported modules) are scanned for name resolution before type inference.
|
||||||
|
* In addition to performing constant cycle checking and reordering, a context is created for type inference (however, most of the information on variables registered in this context is not yet finalized).
|
||||||
|
|
||||||
|
### 3.2 Type checking & inference
|
||||||
|
|
||||||
|
src: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs)
|
||||||
|
|
||||||
* `HIR` has every variable's type information. It is for "High-level Intermediate Representation".
|
* `HIR` has every variable's type information. It is for "High-level Intermediate Representation".
|
||||||
* `ASTLowerer` can be constructed in the same way as `Parser` and `Lexer`.
|
* `ASTLowerer` can be constructed in the same way as `Parser` and `Lexer`.
|
||||||
|
@ -31,19 +54,28 @@
|
||||||
* `ASTLowerer` is owned by `Compiler`. Unlike conventional structures, `ASTLowerer` handles code contexts and is not a one-time disposable.
|
* `ASTLowerer` is owned by `Compiler`. Unlike conventional structures, `ASTLowerer` handles code contexts and is not a one-time disposable.
|
||||||
* If the result of type inference is incomplete (if there is an unknown type variable), an error will occur during name resolution.
|
* If the result of type inference is incomplete (if there is an unknown type variable), an error will occur during name resolution.
|
||||||
|
|
||||||
## 4. Check side-effects (compiler/effectcheck.rs)
|
## 4. Check side-effects
|
||||||
|
|
||||||
## 4. Check ownerships (compiler/memcheck.rs)
|
src: [erg_compiler/effectcheck.rs](../../../crates/erg_compiler/effectcheck.rs)
|
||||||
|
|
||||||
## 5. Desugar `HIR` (compiler/desugar_hir.rs)
|
## 5. Check ownerships
|
||||||
|
|
||||||
|
src: [erg_compiler/ownercheck.rs](../../../crates/erg_compiler/ownercheck.rs)
|
||||||
|
|
||||||
|
## 6. Desugar `HIR`
|
||||||
|
|
||||||
|
src: [erg_compiler/desugar_hir.rs](../../../crates/erg_compiler/desugar_hir.rs)
|
||||||
|
|
||||||
Convert parts that are not consistent with Python syntax
|
Convert parts that are not consistent with Python syntax
|
||||||
|
|
||||||
* Convert class member variables to functions
|
* Convert class member variables to functions
|
||||||
|
|
||||||
## 6. Generate Bytecode (`CodeObj`) from `HIR` (compiler/codegen.rs)
|
## 7. Link
|
||||||
|
|
||||||
## (7. (Future plans) Convert Bytecode -> LLVM IR)
|
src: [erg_compiler/link.rs](../../../crates/erg_compiler/link.rs)
|
||||||
|
|
||||||
* Bytecode is stack-based, whereas LLVM IR is register-based.
|
* Load all modules, resolve dependencies, and combine into a single HIR
|
||||||
There will be several more layers of intermediate processes for this conversion process.
|
|
||||||
|
## 8. Generate Bytecode (`CodeObj`) from `HIR`
|
||||||
|
|
||||||
|
src: [erg_compiler/codegen.rs](../../../crates/erg_compiler/codegen.rs)
|
||||||
|
|
|
@ -26,4 +26,4 @@
|
||||||
|
|
||||||
## [transpile](./transpile.md)
|
## [transpile](./transpile.md)
|
||||||
|
|
||||||
## [type_var_normalization.](type_var_normalization.md)
|
## [type_var_normalization.](type_var_normalization.md)
|
||||||
|
|
|
@ -36,3 +36,7 @@ Increase the thread stack size. Used for Windows execution and test execution.
|
||||||
|
|
||||||
`--language-server` option becomes available.
|
`--language-server` option becomes available.
|
||||||
`erg --language-server` will start the Erg language server.
|
`erg --language-server` will start the Erg language server.
|
||||||
|
|
||||||
|
## py_compatible
|
||||||
|
|
||||||
|
Enable Python-compatible mode, which makes parts of the APIs and syntax compatible with Python. Used for [pylyzer](https://github.com/mtshiba/pylyzer).
|
||||||
|
|
|
@ -7,7 +7,9 @@ Any document that does not follow the rules below is subject to correction.
|
||||||
* Always include definitions, meanings, or links to terms that appear for the first time in the document.
|
* Always include definitions, meanings, or links to terms that appear for the first time in the document.
|
||||||
* Use parentheses as a proviso only for sentences that are supplementary but necessary for understanding the main text, and use footnotes for sentences that are not essential for understanding the main text[<sup id="f1">1</ sup>](#1).
|
* Use parentheses as a proviso only for sentences that are supplementary but necessary for understanding the main text, and use footnotes for sentences that are not essential for understanding the main text[<sup id="f1">1</ sup>](#1).
|
||||||
* If the content of the document is outdated, update it according to [this method](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362).
|
* If the content of the document is outdated, update it according to [this method](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362).
|
||||||
|
* Files under `syntax` should have sequential numbers at the beginning of their file names, except for those not included in the document.
|
||||||
|
* Scripts that automatically insert and replace files exist in doc/script.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<span id="1" style="font-size:x-small"><sup>1</sup> See this for how to write footnotes. [↩](#f1)</span>
|
<span id="1" style="font-size:x-small"><sup>1</sup> See this for how to write footnotes. [↩](#f1)</span>
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
We use pre-commit to have clippy check and test automatically.
|
We use pre-commit to have clippy check and test automatically.
|
||||||
The checks may fail on the first run even if there are no bugs, in which case you should try committing again.
|
The checks may fail on the first run even if there are no bugs, in which case you should try committing again.
|
||||||
|
|
||||||
* Python3 interpreter
|
* Python3 interpreter (3.7~3.11)
|
||||||
|
|
||||||
|
If you want to check the behavior of Erg in various versions, it is recommended to install such as [pyenv](https://github.com/pyenv/pyenv).
|
||||||
|
|
||||||
## Recommendation
|
## Recommendation
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/compiler/architecture.md&commit_hash=a711efa99b325ba1012f6897e7b0e2bdb947d8a1)
|
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/compiler/architecture.md&commit_hash=a711efa99b325ba1012f6897e7b0e2bdb947d8a1)
|
||||||
|
|
||||||
## 1. Erg スクリプト (.er) をスキャンし、`TokenStream` (parser/lex.rs) を生成する
|
## 1. Erg スクリプト (.er) をスキャンし、`TokenStream` を生成する
|
||||||
|
|
||||||
|
src: [erg_parser/lex.rs](../../../crates/erg_parser/lex.rs)
|
||||||
|
|
||||||
* parser/lexer/Lexer が `TokenStream` を生成する (これは `Token` のイテレータである。`TokenStream` は `Lexer::collect()` によって生成できる)
|
* parser/lexer/Lexer が `TokenStream` を生成する (これは `Token` のイテレータである。`TokenStream` は `Lexer::collect()` によって生成できる)
|
||||||
* [`Lexer`](./phases/01_lex.md) は `Lexer::new` または `Lexer::from_str` から構築される。`Lexer::new` はファイルまたはコマンド オプションからコードを読み取る。
|
* [`Lexer`](./phases/01_lex.md) は `Lexer::new` または `Lexer::from_str` から構築される。`Lexer::new` はファイルまたはコマンド オプションからコードを読み取る。
|
||||||
|
@ -11,29 +13,43 @@
|
||||||
* `Lexer` を単体で使用する場合は、代わりに`LexerRunner` を使用します。`Lexer` は単なるイテレータであり、`Runnable` トレイトを実装していない。
|
* `Lexer` を単体で使用する場合は、代わりに`LexerRunner` を使用します。`Lexer` は単なるイテレータであり、`Runnable` トレイトを実装していない。
|
||||||
* `Runnable` は、 `LexerRunner` 、 `ParserRunner` 、 `Compiler` 、および `DummyVM` に実装されている。
|
* `Runnable` は、 `LexerRunner` 、 `ParserRunner` 、 `Compiler` 、および `DummyVM` に実装されている。
|
||||||
|
|
||||||
## 2. `TokenStream` -> `AST` (parser/parse.rs)
|
## 2. `TokenStream` -> `AST`
|
||||||
|
|
||||||
|
src: [erg_parser/parse.rs](../../../crates/erg_parser/parse.rs)
|
||||||
|
|
||||||
* [`Parser`](./phases/02_parse.md) は `Lexer` と同様に `Parser::new` と `Parser::from_str` の 2 つのコンストラクタを持ち、`Parser::parse` は `AST` を返す。
|
* [`Parser`](./phases/02_parse.md) は `Lexer` と同様に `Parser::new` と `Parser::from_str` の 2 つのコンストラクタを持ち、`Parser::parse` は `AST` を返す。
|
||||||
* `AST`は`Vec<Expr>`のラッパー型で、「抽象構文木」を表す。
|
* `AST`は`Vec<Expr>`のラッパー型で、「抽象構文木」を表す。
|
||||||
|
|
||||||
### 2.1 `AST`の脱糖
|
### 2.1 `AST`の脱糖
|
||||||
|
|
||||||
|
src: [erg_parser/desugar.rs](../../../crates/erg_parser/desugar.rs)
|
||||||
|
|
||||||
* [`Desugarer`](./phases/03_desugar.md)
|
* [`Desugarer`](./phases/03_desugar.md)
|
||||||
* パターンマッチを単一の変数代入列へ変換 (`Desugarer::desugar_nest_vars_pattern`)
|
* パターンマッチを単一の変数代入列へ変換 (`Desugarer::desugar_nest_vars_pattern`)
|
||||||
* 複数パターン定義構文をmatchへ変換 (`Desugarer::desugar_multiple_pattern_def`)
|
* 複数パターン定義構文をmatchへ変換 (`Desugarer::desugar_multiple_pattern_def`)
|
||||||
|
|
||||||
|
### 2.2 `AST`の並び替え・結合
|
||||||
|
|
||||||
|
src: [erg_compiler/reorder.rs](../../../crates\erg_compiler\reorder.rs)
|
||||||
|
|
||||||
|
* クラスメソッドをクラス定義に結合する
|
||||||
|
* メソッド定義は定義ファイル外でも可能となっている
|
||||||
|
* 現在の実装は不完全、同一ファイル内のみ
|
||||||
|
|
||||||
## 3. `AST` -> `HIR`
|
## 3. `AST` -> `HIR`
|
||||||
|
|
||||||
(主要な)ソースコード: [erg_compiler/lower.rs](../../../compiler/erg_compiler/lower.rs)
|
(主要な)ソースコード: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs)
|
||||||
|
|
||||||
## 3.1 名前解決
|
## 3.1 名前解決
|
||||||
|
|
||||||
|
現在の実装では型チェック中に行われる
|
||||||
|
|
||||||
* 型推論の前に全てのAST(importされたモジュール含む)を走査し、名前解決を行う
|
* 型推論の前に全てのAST(importされたモジュール含む)を走査し、名前解決を行う
|
||||||
* 定数の循環検査や並び替えなどが行われるほか、型推論のためのContextが作成される(ただし、このContextに登録された変数の情報ははまだ殆どが未確定)
|
* 定数の循環検査や並び替えなどが行われるほか、型推論のためのContextが作成される(ただし、このContextに登録された変数の情報ははまだ殆どが未確定)
|
||||||
|
|
||||||
### 3.2 型チェックと推論
|
### 3.2 型チェックと推論
|
||||||
|
|
||||||
ソースコード: [erg_compiler/lower.rs](../../../compiler/erg_compiler/lower.rs)
|
ソースコード: [erg_compiler/lower.rs](../../../crates/erg_compiler/lower.rs)
|
||||||
|
|
||||||
* `HIR` は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。
|
* `HIR` は、すべての変数の型情報を持っており、「高レベルの中間表現」を表す。
|
||||||
* `ASTLowerer` は Parser や Lexer と同じように構築できる。
|
* `ASTLowerer` は Parser や Lexer と同じように構築できる。
|
||||||
|
@ -43,23 +59,25 @@
|
||||||
|
|
||||||
## 4. 副作用のチェック
|
## 4. 副作用のチェック
|
||||||
|
|
||||||
ソースコード: [erg_compiler/effectcheck.rs](../../../compiler/erg_compiler/effectcheck.rs)
|
ソースコード: [erg_compiler/effectcheck.rs](../../../crates/erg_compiler/effectcheck.rs)
|
||||||
|
|
||||||
## 4. 所有権の確認
|
## 5. 所有権の確認
|
||||||
|
|
||||||
ソースコード: [erg_compiler/ownercheck.rs](../../../compiler/erg_compiler/ownercheck.rs)
|
ソースコード: [erg_compiler/ownercheck.rs](../../../crates/erg_compiler/ownercheck.rs)
|
||||||
|
|
||||||
## 5. `HIR`の脱糖
|
## 6. `HIR`の脱糖
|
||||||
|
|
||||||
ソースコード: [erg_compiler/desugar_hir.rs](../../../compiler/erg_compiler/desugar_hir.rs)
|
ソースコード: [erg_compiler/desugar_hir.rs](../../../crates/erg_compiler/desugar_hir.rs)
|
||||||
|
|
||||||
* Pythonの文法と整合しない部分を変換する
|
* Pythonの文法と整合しない部分を変換する
|
||||||
* クラスのメンバ変数を関数に変換
|
* クラスのメンバ変数を関数に変換
|
||||||
|
|
||||||
## 6. リンク
|
## 7. リンク
|
||||||
|
|
||||||
|
ソースコード: [erg_compiler/link.rs](../../../crates/erg_compiler/link.rs)
|
||||||
|
|
||||||
* 全てのモジュールを読み込み、依存関係を解決し、単一のHIRに結合する
|
* 全てのモジュールを読み込み、依存関係を解決し、単一のHIRに結合する
|
||||||
|
|
||||||
## 7. `HIR` からバイトコード (`CodeObj`) を生成
|
## 8. `HIR` からバイトコード (`CodeObj`) を生成
|
||||||
|
|
||||||
ソースコード: [erg_compiler/codegen.rs](../../../compiler/erg_compiler/codegen.rs)
|
ソースコード: [erg_compiler/codegen.rs](../../../crates/erg_compiler/codegen.rs)
|
||||||
|
|
|
@ -38,3 +38,7 @@ Erg 内部オプション、ヘルプ (ヘルプ、著作権、ライセンス
|
||||||
|
|
||||||
`--language-server`オプションが利用可能になる。
|
`--language-server`オプションが利用可能になる。
|
||||||
`erg --language-server`でLanguage Serverが起動する。
|
`erg --language-server`でLanguage Serverが起動する。
|
||||||
|
|
||||||
|
## py_compatible
|
||||||
|
|
||||||
|
Python互換モードを有効にする。APIや文法の一部がPythonと互換になる。[pylyzer](https://github.com/mtshiba/pylyzer)のために使用される。
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
* ドキュメント内で初出の用語は、必ず定義や意味、またはリンクを併記する。
|
* ドキュメント内で初出の用語は、必ず定義や意味、またはリンクを併記する。
|
||||||
* ただし書きとしての()は、補助的ではあるものの本文の理解に必要な文の場合のみ使用し、本文の理解に必須でない文は脚注を使用する[<sup id="f1">1</sup>](#1)。
|
* ただし書きとしての()は、補助的ではあるものの本文の理解に必要な文の場合のみ使用し、本文の理解に必須でない文は脚注を使用する[<sup id="f1">1</sup>](#1)。
|
||||||
* ドキュメントの内容が古くなっていた場合は、[この方法](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362)に従って更新する。
|
* ドキュメントの内容が古くなっていた場合は、[この方法](https://github.com/erg-lang/erg/issues/48#issuecomment-1218247362)に従って更新する。
|
||||||
|
* syntax以下のファイルは、ドキュメントに含めないものを除きファイル名の頭に連番を付ける。
|
||||||
|
* 挿入や入れ替えを自動で行うスクリプトがdoc/script内に存在する。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
pre-commitを使ってclippyのチェックやテストを自動で行わせています。
|
pre-commitを使ってclippyのチェックやテストを自動で行わせています。
|
||||||
バグがなくても最初の実行でチェックが失敗する場合があります。その場合はもう一度コミットを試みてください。
|
バグがなくても最初の実行でチェックが失敗する場合があります。その場合はもう一度コミットを試みてください。
|
||||||
|
|
||||||
* Python3インタープリタ
|
* Python3インタープリタ (3.7~3.11)
|
||||||
|
|
||||||
|
様々なバージョンでErgの挙動を検査したい場合は [pyenv](https://github.com/pyenv/pyenv) 等の導入をお勧めします。
|
||||||
|
|
||||||
## 推奨
|
## 推奨
|
||||||
|
|
||||||
|
|
23
doc/scripts/align_files.py
Normal file
23
doc/scripts/align_files.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
|
||||||
|
"""
|
||||||
|
Align file prefixes when they are not numbered consecutively.
|
||||||
|
existing files: 01_foo.md, 03_bar.md, 04_baz.md
|
||||||
|
result: 01_foo.md, 02_bar.md, 03_baz.md
|
||||||
|
"""
|
||||||
|
if __name__ == '__main__':
|
||||||
|
prev = None
|
||||||
|
diff = None
|
||||||
|
for f in sorted(glob.glob("[0-9][0-9]_*")):
|
||||||
|
if prev != None:
|
||||||
|
now_file_no = int(f.split("_")[0])
|
||||||
|
diff = now_file_no - prev
|
||||||
|
if diff != 1:
|
||||||
|
replace_to = "_".join([f"{now_file_no-diff+1:02d}", *f.split("_")[1:]])
|
||||||
|
os.rename(f, replace_to)
|
||||||
|
prev = now_file_no - diff + 1
|
||||||
|
else:
|
||||||
|
prev = now_file_no
|
||||||
|
else:
|
||||||
|
prev = int(f.split("_")[0])
|
43
doc/scripts/insert_file.py
Normal file
43
doc/scripts/insert_file.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import glob
|
||||||
|
|
||||||
|
"""
|
||||||
|
Insert a file into files followed by a sequential number. Existing files are shifted by one.
|
||||||
|
example:
|
||||||
|
existing files: 01_foo.md, 02_bar.md, 03_baz.md
|
||||||
|
1st arg(inserting file): qux.md
|
||||||
|
2nd arg(file no): 2
|
||||||
|
result: 01_foo.md, 02_qux.md, 03_bar.md, 04_baz.md
|
||||||
|
"""
|
||||||
|
if __name__ == '__main__':
|
||||||
|
file = sys.argv[1]
|
||||||
|
file_no = sys.argv[2]
|
||||||
|
if not file_no.isdigit():
|
||||||
|
raise ValueError('File number must be a number')
|
||||||
|
else:
|
||||||
|
file_no = int(file_no)
|
||||||
|
|
||||||
|
if len(glob.glob("_[0-9][0-9]_*")) > 0:
|
||||||
|
raise Exception("Escaped file already exists, rename it")
|
||||||
|
# escaping
|
||||||
|
for esc in sorted(glob.glob("[0-9][0-9]_*")):
|
||||||
|
if int(esc.split("_")[0]) < file_no: continue
|
||||||
|
else: os.rename(esc, "_" + esc)
|
||||||
|
|
||||||
|
target = f"{file_no:02d}_" + file
|
||||||
|
if os.path.exists(target):
|
||||||
|
raise OSError(f"File {target} already exists")
|
||||||
|
os.rename(file, target)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
nxt = glob.glob(f"_{file_no:02d}_*")
|
||||||
|
if len(nxt) == 0:
|
||||||
|
exit(0)
|
||||||
|
elif len(nxt) >= 2:
|
||||||
|
raise ValueError("More than one file with the same number")
|
||||||
|
else:
|
||||||
|
target = nxt[0]
|
||||||
|
replace_to = "_".join([f"{file_no+1:02d}", *target.split("_")[2:]])
|
||||||
|
os.rename(target, replace_to)
|
||||||
|
file_no += 1
|
Loading…
Add table
Add a link
Reference in a new issue