diff --git a/CLAUDE.md b/CLAUDE.md index 068af96..850bd16 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -82,6 +82,7 @@ Blocks support fence options (e.g., ` ```nushell try, no-output `): - `try` / `t`: Wrap in try-catch - `new-instance` / `n`: Execute in separate Nushell instance - `separate-block` / `s`: Output results in separate code block instead of inline `# =>` +- `run-once`: Execute code block once, then set to `no-run` ### Output Format Conventions diff --git a/numd/commands.nu b/numd/commands.nu index 883793d..b035146 100644 --- a/numd/commands.nu +++ b/numd/commands.nu @@ -256,7 +256,7 @@ export def decorate-original-code-blocks [ | insert code {|i| $i.line | process-code-block-content ($i.row_type | extract-fence-options) - | generate-block-markers $i.block_index $i.row_type + | generate-block-markers $i.block_index ($i.row_type | str replace 'run-once' 'no-run') } } @@ -648,7 +648,7 @@ export def generate-block-markers [ } # Parse options from a code fence and return them as a list. -@example "parse fence options with short forms" { '```nu no-run, t' | extract-fence-options } --result [no-run, try] +@example "parse fence options with short forms" { '```nu no-run, t' | extract-fence-options } --result [no-run try] export def extract-fence-options []: string -> list { str replace -r '```nu(shell)?\s*' '' | split row ',' diff --git a/tests/test_commands.nu b/tests/test_commands.nu index a232bef..19ab290 100644 --- a/tests/test_commands.nu +++ b/tests/test_commands.nu @@ -82,6 +82,16 @@ def "classify-block-action returns print-as-it-is for no-run" [] { assert equal (classify-block-action "```nushell no-run") "print-as-it-is" } +@test +def "classify-block-action returns execute for run-once" [] { + assert equal (classify-block-action "```nushell run-once") "execute" +} + +@test +def "classify-block-action returns execute for run-once combined with try" [] { + assert equal (classify-block-action "```nushell run-once, try") "execute" +} + @test def "classify-block-action returns delete for output-numd" [] { assert equal (classify-block-action "```output-numd") "delete" @@ -126,6 +136,22 @@ def "extract-fence-options expands short options" [] { assert ("no-output" in $result) } +@test +def "extract-fence-options parses run-once" [] { + let result = "```nu run-once" | extract-fence-options + + assert equal $result ["run-once"] +} + +@test +def "extract-fence-options parses run-once combined with try" [] { + let result = "```nu run-once, try" | extract-fence-options + + assert equal ($result | length) 2 + assert ("run-once" in $result) + assert ("try" in $result) +} + @test def "extract-fence-options handles empty options" [] { let result = "```nushell" | extract-fence-options @@ -375,6 +401,37 @@ def "generate-timestamp returns correct format" [] { assert ($result =~ '^\d{8}_\d{6}$') } +# ============================================================================= +# Tests for decorate-original-code-blocks (run-once rewriting) +# ============================================================================= + +@test +def "decorate-original-code-blocks rewrites run-once to no-run" [] { + let blocks = "```nu run-once\necho hello\n```" | parse-markdown-to-blocks + let result = decorate-original-code-blocks $blocks + + assert ($result.0.code =~ '```nu no-run') + assert ($result.0.code !~ 'run-once') +} + +@test +def "decorate-original-code-blocks rewrites run-once preserving other options" [] { + let blocks = "```nu run-once, try\necho hello\n```" | parse-markdown-to-blocks + let result = decorate-original-code-blocks $blocks + + assert ($result.0.code =~ '```nu no-run, try') + assert ($result.0.code !~ 'run-once') +} + +@test +def "decorate-original-code-blocks leaves plain blocks unchanged" [] { + let blocks = "```nu\necho hello\n```" | parse-markdown-to-blocks + let result = decorate-original-code-blocks $blocks + + assert ($result.0.code =~ '```nu') + assert ($result.0.code !~ 'no-run') +} + # ============================================================================= # Tests for strip-outputs # ============================================================================= diff --git a/z_examples/6_edge_cases/run_once.md b/z_examples/6_edge_cases/run_once.md new file mode 100644 index 0000000..f2241f9 --- /dev/null +++ b/z_examples/6_edge_cases/run_once.md @@ -0,0 +1,13 @@ +# run-once fence option + +After numd run, the run-once block below should become no-run with output preserved. + +```nu run-once +2 + 2 +``` + +This block uses run-once combined with no-output. + +```nu run-once, no-output +3 + 3 +```