diff --git a/README.md b/README.md index 0c8387f..b74f0d6 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,164 @@ def fizz_buzz(): と書く。 +### assert-codeblock upd-exact + +| 構文 | `assert-codeblock upd-exact 新ファイル名` | +|--|--| +| 役割 | ローカル実行時は、教材に引用されているコードで新ファイルを置き換える。
github-action 実行時は exact として動作する| + +たとえば、`sample_files/2-1.py` を + +```python +def hello(): + print("Hello, World!") + +hello() +``` + +としたいときは、 + +````markdown + + +```python +def hello(): + print("Hello, World!") + +hello() +``` +```` + +と書く。 + +なお、upd-exact をローカル実行した場合は、置き換え処理だけが行われ検査は実行されない。 +対して、github-actionsで実行した場合は、exactとして起動するため完全一致を検査し、ファイルの置き換えは実行されない。 + +### assert-codeblock upd-diff + +| 構文 | `assert-codeblock upd-diff 旧ファイル 新ファイル` | +|--|--| +| 役割 | ローカル実行時は、教材に引用されている diff 適用前のコードが旧ファイルと一致するかを検査する。問題なければ新ファイルに diff 適用後のファイルを書き出す。
github-action 実行時は diff として動作する | + +たとえば、`sample_files/2-1.py` に + +```python +def hello(): + print("Hello, World!") + +hello() +``` + +とあるとき、 + +````markdown + + +```diff-python + def hello(): + print("Hello, World!") + +-hello() ++for x in range(6): ++ hello() +``` +```` + +と書く。 + +検査が問題なければ、`sample_files/2-2.py` は以下の内容で更新される。 + +```python +def hello(): + print("Hello, World!") + +for x in range(6): + hello() +``` + +なお、github-actions で実行した場合は、diff として起動するため、ファイルの置き換えは実行されない。 + +### assert-codeblock upd-partial + +| 構文 | `assert-codeblock upd-partial 旧ファイル 新ファイル 行番号` | +|--|--| +| 役割 | 教材に引用されているコードを、旧ファイルの n 行目から適用して、新ファイルを書き出す。
github-action 実行時は、partial 新ファイル 行番号として起動する| + +たとえば、`sample_files/2-2.py` に + +```python +def hello(): + print("Hello, World!") + +for x in range(6): + hello() +``` + +と書いてあるとき、これの 7 行目から新たにコードを追加したい場合 + +````markdown + + +```python +print("Hello") +``` +```` + +と書く。 + +適用できれば、`sample_files/2-3.py` は以下の内容で更新される。 + +```python +def hello(): + print("Hello, World!") + +for x in range(6): + hello() + +print("Hello") +``` + +なお、このコマンドは、通常のコードブロックを使って、コード追加する指示をしているときに使うことを想定している。
+コード解説のような、更新を指示しないものについては、partial や exact を利用する。 + +他のコマンド同様に、github-actions で実行した場合は、partial として起動するため、ファイルの置き換えは実行されない。 + +### assert-codeblock upd-diff-partial + +| 構文 | `assert-codeblock upd-diff-partial 旧ファイル名 新ファイル 行番号` | +|--|--| +| 役割 | ローカル実行時は、教材に n 行目から抜粋されている diff 適用前のコードが旧ファイルと一致するかを検査する。問題なければ新ファイルに diff 適用後のファイルを書き出す。
github-action 実行時は diff-partial として動作する | + +たとえば、`sample_files/2-3.py` に + +```python +def hello(): + print("Hello, World!") + +for x in range(6): + hello() + +print("Hello") +``` + +とあり、2行目から引用して、差分更新をしたい場合 + +````markdown + + +```diff-python + print("Hello, World!") + +-for x in range(6): ++for x in range(5): + hello() +``` + +```` + +と書く。 + +なお、github-actions で実行した場合は、diff-partial として起動するため、ファイルの置き換えは実行されない。 ## テスト方法 diff --git a/assert-codeblock.js b/assert-codeblock.js new file mode 100644 index 0000000..f5b6493 --- /dev/null +++ b/assert-codeblock.js @@ -0,0 +1,7 @@ +const AssertCodeblock = require('./dist/index'); +const config = { + src: "./sample_files/" +}; + +const textbook_filepath = `README.md`; +AssertCodeblock.inspect_codeblock(textbook_filepath, config) // true \ No newline at end of file diff --git a/src/command.ts b/src/command.ts index 02888da..18d27be 100644 --- a/src/command.ts +++ b/src/command.ts @@ -3,6 +3,7 @@ import path from 'node:path'; import { Config, FILTER, TestRes, WrongFileNameInCommandError, readFileSync, trimEndOnAllLines } from "./util"; import { structuredPatch } from 'diff'; import { PatchApplyError, apply_diff, apply_diff_on_lines } from "./apply_diff"; +import fs from "fs"; function handle_exact(textbook_filepath: string, command_args: string[], matched_file_content: string, src_folder: string, matched_label_line_num: number): TestRes { const sample_file_name = command_args[1]; @@ -175,7 +176,7 @@ The line number "${command_args[2]}" is not a number`, const sample_file_name = command_args[1]; - const sample_file_path = path.join(src_folder , sample_file_name); + const sample_file_path = path.join(src_folder, sample_file_name); const sample_file_content = readFileSync(sample_file_path, command_args.join(" "), matched_label_line_num).replace(/\r?\n/g, "\n"); // 末尾の改行を削って行数を数える @@ -277,8 +278,8 @@ ${mes}`, } } - const old_sample_file_path = path.join(src_folder , old_sample_file_name); - const new_sample_file_path = path.join(src_folder , new_sample_file_name); + const old_sample_file_path = path.join(src_folder, old_sample_file_name); + const new_sample_file_path = path.join(src_folder, new_sample_file_name); const code_block_label = command_args.join(" "); const oldStr = readFileSync(old_sample_file_path, code_block_label, matched_label_line_num); const newStr = readFileSync(new_sample_file_path, code_block_label, matched_label_line_num); @@ -381,8 +382,429 @@ with the code block labeled "${command_args.join(" ")}"`, } } +function handle_upd_exact(textbook_filepath: string, command_args: string[], expected_new_content: string, src_folder: string, matched_line_num: number): TestRes { + const code_block_label = command_args.join(" "); + const new_sample_file_name = command_args[1]; + const new_sample_file_path = path.join(src_folder, new_sample_file_name); + if (!fs.existsSync(new_sample_file_path)) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdExact", + result_type: "CreatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" の内容で "${new_sample_file_path}" のファイルを作りました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + const new_content = readFileSync(new_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + if (expected_new_content !== new_content) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdExact", + result_type: "UpdatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" と "${new_sample_file_path}" が不一致のため、ファイルを置き換えました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } else { + return { + is_success: true, + body: { + command_type: "UpdExact", + result_type: "Success", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" は "${new_sample_file_path}" と一致しています`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } +} + +function handle_upd_diff(textbook_filepath: string, command_args: string[], diff_content: string, src_folder: string, matched_line_num: number): TestRes { + const code_block_label = command_args.join(" "); + const old_sample_file_name = command_args[1]; + const new_sample_file_name = command_args[2]; + const old_sample_file_path = path.join(src_folder, old_sample_file_name); + const new_sample_file_path = path.join(src_folder, new_sample_file_name); + const old_content = readFileSync(old_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + const old_diff_content = diff_content.split("\n").filter((line) => !(line[0] === "+")).map((line) => line.slice(1)).join("\n"); + + const actual_diff = (() => { + const diff = structuredPatch("textbook", old_sample_file_path, old_diff_content, old_content, "", "", { context: 1e6 }); + + const ret: string[] = []; + for (let i = 0; i < diff.hunks.length; i++) { + ret.push(...diff.hunks[i].lines); + } + return ret.join('\n'); + })(); + + // パッチ適用前と旧ファイルに差がある場合は、エラーを吐く + if (actual_diff) { + return { + is_success: false, + body: { + command_type: "UpdDiff", + result_type: "Mismatch", + message: ` MISMATCH FOUND +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +The diff of ${old_sample_file_path} with textbook is as follows: \n\`\`\`\n${actual_diff}\n\`\`\` +`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + message_except_content: ` MISMATCH FOUND +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}"`, + codeblock_label: code_block_label, + textbook_content: diff_content, + sample_content: actual_diff, + } + }; + } + + try { + // パッチ適用後ファイルの作成 + const expected_new_content = apply_diff(old_content, trimEndOnAllLines(diff_content)) + + // ファイルが無い場合は作成 + if (!fs.existsSync(new_sample_file_path)) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdDiff", + result_type: "CreatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" のパッチ適用前は旧ファイルと一致しています。新ファイルがないので、パッチ適用後の内容で新ファイルを作りました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がある場合は、置き換え + const new_content = readFileSync(new_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + if (expected_new_content !== new_content) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdDiff", + result_type: "UpdatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" のパッチ適用前は旧ファイルと一致しています。パッチ適用後の内容と新ファイルの内容が不一致のため、新ファイルを置き換えました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がない場合は、コメントのみ + return { + is_success: true, + body: { + command_type: "UpdDiff", + result_type: "Success", + message: + ` OK: "${textbook_filepath}" のコードブロック "${code_block_label}" のパッチ適用前は旧ファイルと、パッチ適用後は新ファイルと一致しています`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } catch (e) { + if (e instanceof PatchApplyError) { + return { + is_success: false, + body: { + command_type: "UpdDiff", + result_type: "Mismatch", + message: ` CANNOT APPLY THE PATCH +[original message: \`${e.message}\`] +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +The content of ${old_sample_file_path} is as follows: \n\`\`\`\n${old_content}\`\`\` +The patch in the textbook is as follows: \n\`\`\`\n${diff_content}\`\`\` `, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + message_except_content: ` CANNOT APPLY THE PATCH +[original message: \`${e.message}\`] +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}"`, + codeblock_label: code_block_label, + } + } + } else { throw e; } + } +} + +function handle_upd_partial(textbook_filepath: string, command_args: string[], additional_content: string, src_folder: string, matched_line_num: number): TestRes { + const code_block_label = command_args.join(" "); + const old_sample_file_name = command_args[1]; + const new_sample_file_name = command_args[2]; + + if (command_args[3] === undefined) { + return { + is_success: false, + body: { + command_type: "UpdPartial", + result_type: "LineNumMissing", + message: ` INSUFFICIENT ARGUMENT: LINE NUMBER MISSING +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +Note that 'assert-codeblock upd-partial' requires two file names AND one's line number: +for example, `, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + } + } + const starting_line_num = Number(command_args[3]); + + const old_sample_file_path = path.join(src_folder, old_sample_file_name); + const new_sample_file_path = path.join(src_folder, new_sample_file_name); + + const old_content = readFileSync(old_sample_file_path, code_block_label.replace(/\r?\n/g, "\n"), matched_line_num); + + // 末尾のブランクを削って行数を数える + const old_content_trimend = old_content.trimEnd(); + const old_content_last_line_num = old_content_trimend.split("\n").length; + + // 旧ファイルの行数とコードブロックの行番号が被っている場合、エラーを吐く + if (starting_line_num <= old_content_last_line_num) { + return { + is_success: false, + body: { + command_type: "UpdPartial", + result_type: "LineNumDuplication", + message: ` MISMATCH FOUND +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +The content of ${old_sample_file_path} already has a line whose number is ${starting_line_num}`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + textbook_content: additional_content, + sample_content: old_content, + } + } + } + + // 新ファイルの作成 + const expected_new_content = old_content_trimend + "\n".repeat(starting_line_num - old_content_last_line_num) + additional_content; + + if (!fs.existsSync(new_sample_file_path)) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdPartial", + result_type: "CreatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" の内容で "${new_sample_file_path}" のファイルを作りました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がある場合は、置き換え + const newContent = readFileSync(new_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + if (expected_new_content !== newContent) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdPartial", + result_type: "UpdatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" は "${new_sample_file_path}" と一致しています`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がない場合は、コメントのみ + return { + is_success: true, + body: { + command_type: "UpdPartial", + result_type: "Success", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" は "${new_sample_file_path}" と一致しています`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; +} + +function handle_upd_diff_partial(textbook_filepath: string, command_args: string[], diff_content: string, src_folder: string, matched_line_num: number): TestRes { + const code_block_label = command_args.join(" "); + const old_sample_file_name = command_args[1]; + const new_sample_file_name = command_args[2]; + if (command_args[3] === undefined) { + return { + is_success: false, + body: { + command_type: "UpdDiffPartial", + result_type: "LineNumMissing", + message: ` INSUFFICIENT ARGUMENT: LINE NUMBER MISSING +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +Note that 'assert-codeblock upd-diff-partial' requires two file names AND one's line number at which the diff starts: +for example, , in which the line numbers start at 13.`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + } + } + const starting_line_num = Number(command_args[3]) - 1; + + const old_sample_file_path = path.join(src_folder, old_sample_file_name); + const new_sample_file_path = path.join(src_folder, new_sample_file_name); + + const old_diff_str = diff_content.split("\n").filter((line) => !(line[0] === "+")).map((line, i) => (line.slice(1))).join("\n"); + const old_diff_str_line_count = old_diff_str.split("\n").length - 1; + const old_content = readFileSync(old_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + const old_str_front = old_content.split("\n").filter((line, i) => (i < starting_line_num)).map((line, i) => (line + "\n")).join(""); + const old_str = old_content.split("\n").filter((line, i) => (i >= starting_line_num) && (i < starting_line_num + old_diff_str_line_count)).map((line, i) => (line + "\n")).join(""); + const old_str_behind = old_content.split("\n").filter((line, i) => (i >= starting_line_num + old_diff_str_line_count)).join("\n"); + + const entire_diff = (() => { + const diff = structuredPatch("textbook", old_sample_file_path, old_diff_str, old_str, "", "", { context: 1e6 }); + + const ret: string[] = []; + for (let i = 0; i < diff.hunks.length; i++) { + ret.push(...diff.hunks[i].lines); + } + return ret.join('\n'); + })(); + + // パッチ適用前と旧ファイルに差がある場合は、エラーを吐く + if (entire_diff) { + return { + is_success: false, + body: { + command_type: "UpdDiffPartial", + result_type: "Mismatch", + message: ` MISMATCH FOUND +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +The diff of ${old_sample_file_path} with textbook is as follows: \n\`\`\`\n${entire_diff}\n\`\`\` +`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + textbook_content: diff_content, + sample_content: entire_diff, + } + }; + } + + try { + + // パッチ適用後ファイルの作成 + const expected_new_content = old_str_front + apply_diff(old_str, trimEndOnAllLines(diff_content)) + old_str_behind; + + // ファイルが無い場合は作成 + if (!fs.existsSync(new_sample_file_path)) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdDiffPartial", + result_type: "CreatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" のパッチ適用前の部分は旧ファイルの部分と一致しています。新ファイルがないので、パッチ適用後の内容で新ファイルを作りました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がある場合は、置き換え + const new_content = readFileSync(new_sample_file_path, code_block_label, matched_line_num).replace(/\r?\n/g, "\n"); + if (expected_new_content !== new_content) { + fs.writeFileSync(new_sample_file_path, expected_new_content) + return { + is_success: true, + body: { + command_type: "UpdDiffPartial", + result_type: "UpdatedFile", + message: + ` OK: "${textbook_filepath}:${matched_line_num}" のコードブロック "${code_block_label}" のパッチ適用前の部分は旧ファイルの部分と一致しています。パッチ適用後の内容と新ファイルの内容が不一致のため、新ファイルを置き換えました`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } + + // コンテンツに差がない場合は、コメントのみ + return { + is_success: true, + body: { + command_type: "UpdDiffPartial", + result_type: "Success", + message: + ` OK: "${textbook_filepath}" のコードブロック "${code_block_label}" のパッチ適用前の部分は旧ファイルの部分と、パッチ適用後の内容は新ファイルの内容と一致しています`, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + codeblock_label: code_block_label, + } + }; + } catch (e) { + if (e instanceof PatchApplyError) { + return { + is_success: false, + body: { + command_type: "UpdDiffPartial", + result_type: "Mismatch", + message: ` CANNOT APPLY THE PATCH +[original message: \`${e.message}\`] +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}" +The partial content of ${old_sample_file_path} is as follows: \n\`\`\`\n${old_str}\`\`\` +The partial patch in the textbook is as follows: \n\`\`\`\n${diff_content}\`\`\` `, + textbook_filepath: textbook_filepath, + codeblock_line_num: matched_line_num, + message_except_content: ` CANNOT APPLY THE PATCH +[original message: \`${e.message}\`] +in ${textbook_filepath}:${matched_line_num} +with the code block labeled "${code_block_label}"`, + codeblock_label: code_block_label, + textbook_content: diff_content, + sample_content: old_str, + } + } + } else { throw e; } + } +} export function run_command_and_get_result(textbook_filepath: string, command: string, matched_file_content: string, config: Config, matched_line_num:number=-1): TestRes { try { @@ -395,6 +817,32 @@ export function run_command_and_get_result(textbook_filepath: string, command: s return handle_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); } else if (command_args[0] === "diff-partial") { return handle_diff_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } else if (command_args[0] === "upd-exact") { + if (process.env.GITHUB_ACTIONS) { + return handle_exact(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } else { + return handle_upd_exact(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } + } else if (command_args[0] === "upd-diff") { + if (process.env.GITHUB_ACTIONS) { + return handle_diff(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } else { + return handle_upd_diff(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } + } else if (command_args[0] === "upd-partial") { + + if (process.env.GITHUB_ACTIONS) { + command_args.splice(1, 1); + return handle_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } else { + return handle_upd_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } + } else if (command_args[0] === "upd-diff-partial") { + if (process.env.GITHUB_ACTIONS) { + return handle_diff_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } else { + return handle_upd_diff_partial(textbook_filepath, command_args, matched_file_content, config.src, matched_line_num); + } } else { return { is_success: false, diff --git a/src/index.ts b/src/index.ts index c8ffb3d..7ce0fc5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -212,13 +212,17 @@ export async function rename_src_files( } } - if (command_args[0] === "exact" || command_args[0] === "partial") { + if (["exact", "partial","upd-exact"].includes(command_args[0])) { // `assert-codeblock exact ファイル名` // `assert-codeblock partial ファイル名 行番号` + // `assert-codeblock upd-exact ファイル名` command_args[1] = replace(command_args[1], replacements); - } else if (command_args[0] === "diff" || command_args[0] === "diff-partial") { + } else if (["diff", "diff-partial", "upd-diff","upd-diff-partial","upd-partial"].includes(command_args[0])) { // `assert-codeblock diff 旧ファイル 新ファイル` - // `assert-codeblock diff-partial 旧ファイル名 新ファイル 行番号` または `assert-codeblock diff-partial 旧ファイル名 新ファイル 新ファイルの行番号 旧ファイルの行番号` + // `assert-codeblock diff-partial 旧ファイル名 新ファイル 行番号` または `assert-codeblock diff-partial 旧ファイル名 新ファイル 新ファイルの行番号 旧ファイルの行番号` + // `assert-codeblock upd-diff 旧ファイル 新ファイル` + // `assert-codeblock upd-diff-partial 旧ファイル名 新ファイル 行番号` + // `assert-codeblock upd-partial 旧ファイル名 新ファイル 行番号` command_args[1] = replace(command_args[1], replacements); command_args[2] = replace(command_args[2], replacements); } else { diff --git a/src/util.ts b/src/util.ts index 263caf2..456e524 100644 --- a/src/util.ts +++ b/src/util.ts @@ -14,8 +14,30 @@ Cannot find a file "${file_name}" mentioned in the code block labeled "${code_bl return fs.readFileSync(file_name, { encoding: "utf-8" }); } -export type CommandType = "Exact" | "Diff" | "Partial" | "DiffPartial" | "Undefined"; -export type ResultType = "Success" | "Mismatch" | "TextbookNotFound" | "WrongFileNameInCommand" | "LineNumMismatch" | "LineNumMissing" | "LineNumNotNumber" | "UnknownCommand" | "UnknownError"; +export type CommandType = + | "Exact" + | "Diff" + | "Partial" + | "DiffPartial" + | "UpdExact" + | "UpdDiff" + | "UpdPartial" + | "UpdDiffPartial" + | "Undefined"; + +export type ResultType = + | "Success" + | "CreatedFile" + | "UpdatedFile" + | "Mismatch" + | "TextbookNotFound" + | "WrongFileNameInCommand" + | "LineNumMismatch" + | "LineNumDuplication" + | "LineNumMissing" + | "LineNumNotNumber" + | "UnknownCommand" + | "UnknownError"; export type ResBody = { command_type: CommandType,