Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use numd; numd clear-outputs path/to/file.md --strip-markdown --echo

1. **`find-code-blocks`**: Parses markdown into a table classifying each block by type (`text`, ` ```nushell `, ` ```output-numd `) and action (`execute`, `print-as-it-is`, `delete`)

2. **`decortate-original-code-blocks`** + **`generate-intermediate-script`**: Transforms executable code blocks into a temporary `.nu` script with markers for output capture
2. **`decorate-original-code-blocks`** + **`generate-intermediate-script`**: Transforms executable code blocks into a temporary `.nu` script with markers for output capture

3. **`execute-intermediate-script`**: Runs the generated script in a new Nushell instance, capturing stdout

Expand Down
64 changes: 36 additions & 28 deletions numd/commands.nu
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export def run [
# We don't use a temp directory here as the code in `md` files might contain relative paths,
# which will only work if we execute the intermediate script from the same folder.

decortate-original-code-blocks $original_md_table
decorate-original-code-blocks $original_md_table
| generate-intermediate-script
| save -f $intermediate_script_path

Expand Down Expand Up @@ -190,8 +190,8 @@ export def --env 'capture stop' []: nothing -> nothing {

# Beautify and adapt the standard `--help` for markdown output
export def 'parse-help' [
--sections: list<string>
--record
--sections: list<string> # filter to only include these sections (e.g., ['Usage', 'Flags'])
--record # return result as a record instead of formatted string
]: string -> any {
let help_lines = split row '======================'
| first # quick fix for https://github.com/nushell/nushell/issues/13470
Expand Down Expand Up @@ -257,7 +257,7 @@ export def 'parse-help' [
}

####
# I keep commands here with `export` to make them availible for testing script, yet I do not export them in the mod.nu
# I keep commands here with `export` to make them available for testing script, yet I do not export them in the mod.nu
###

# Detect code blocks in a markdown string and return a table with their line numbers and info strings.
Expand Down Expand Up @@ -322,8 +322,8 @@ export def match-action [
#
# > 'ls | sort-by modified -r' | create-execution-code --whole_block ['no-output'] | save z_examples/999_numd_internals/create-execution-code_0.nu -f
export def create-execution-code [
fence_options: list<string>
--whole_block
fence_options: list<string> # options from the code fence (e.g., 'no-output', 'try')
--whole_block # treat input as a complete block rather than a single line
]: string -> string {
let code_content = $in
# let fence_options = $env.numd.current_block_options
Expand Down Expand Up @@ -351,9 +351,9 @@ export def create-execution-code [
$highlighted_command + $code_execution
}

# generates additional service code necessary for execution and capturing results, while preserving the original code.
export def decortate-original-code-blocks [
md_classified: table<block_index: int, row_type: string, line: list<string>, action: string>
# Generate additional service code necessary for execution and capturing results, while preserving the original code.
export def decorate-original-code-blocks [
md_classified: table<block_index: int, row_type: string, line: list<string>, action: string> # classified markdown table from find-code-blocks
]: nothing -> table<block_index: int, row_type: string, line: list<string>, action: string, code: string> {
$md_classified
| where action == 'execute'
Expand All @@ -365,6 +365,8 @@ export def decortate-original-code-blocks [
}

# Generate an intermediate script from a table of classified markdown code blocks.
#
# Takes decorated code blocks and produces a complete Nushell script ready for execution.
export def generate-intermediate-script []: table<block_index: int, row_type: string, line: list<string>, action: string, code: string> -> string {
get code -o
| if $env.numd?.prepend-code? != null {
Expand All @@ -383,8 +385,11 @@ export def generate-intermediate-script []: table<block_index: int, row_type: st
| str replace -r "\\s*$" "\n"
}

# Process lines within a code block and generate execution code for each line.
#
# Handles both REPL-style blocks (lines starting with '>') and whole-block execution.
export def execute-block-lines [
fence_options: list<string>
fence_options: list<string> # options from the code fence (e.g., 'no-output', 'try')
]: list<string> -> list<string> {
skip | drop # skip code fences
| if ($in | where $it =~ '^>' | is-empty) {
Expand Down Expand Up @@ -563,10 +568,10 @@ export def escape-special-characters-and-quote []: string -> string {
| $'"($in)"'
}

# Run the intermediate script and return its output lines as a list.
# Run the intermediate script and return its output as a string.
export def execute-intermediate-script [
intermed_script_path: path
no_fail_on_error: bool
intermed_script_path: path # path to the generated intermediate script
no_fail_on_error: bool # if true, return empty string on error instead of failing
print_block_results: bool # print blocks one by one as they execute
]: nothing -> string {
(
Expand Down Expand Up @@ -607,14 +612,14 @@ export def create-highlight-command []: string -> string {
| $"($in) | nu-highlight | print(char nl)(char nl)"
}

# Trim comments and extra whitespaces from code blocks for use in the generated script.
# Trim comments and extra whitespace from code blocks for use in the generated script.
export def remove-comments-plus []: string -> string {
str replace -r '^[>\s]+' '' # trim starting `>`
| str replace -r '[\s\n]+$' '' # trim newlines and spaces from the end of a line
| str replace -r '\s+#.*$' '' # remove comments from the last line. Might spoil code blocks with the # symbol, used not for commenting
| str replace -r '\s+#.*$' '' # remove comments from the last line. May affect code blocks where # is used for non-comment purposes
}

# Extract the last span from a command to determine if `| print` can be appended
# Extract the last span from a command to determine if `| print` can be appended.
#
# > get-last-span 'let a = 1..10; $a | length'
# length
Expand Down Expand Up @@ -659,7 +664,7 @@ export def get-last-span [
| str substring $len..
}

# Check if the last span of the input ends with a semicolon or contains certain keywords to determine if appending ` | print` is possible.
# Check if the command can have `| print` appended by analyzing its last span for semicolons or declaration keywords.
#
# > check-print-append 'let a = ls'
# false
Expand All @@ -686,7 +691,7 @@ export def check-print-append [
# > 'ls' | create-indented-output
# ls | table | lines | each {$'# => ($in)' | str trim --right} | str join (char nl)
export def create-indented-output [
--indent: string = '# => '
--indent: string = '# => ' # prefix string for each output line
]: string -> string {
generate-table-statement
| $"($in) | default '' | into string | lines | each {$'($indent)\($in\)' | str trim --right} | str join \(char nl\) | str replace -r '\\s*$' \"\\n\""
Expand Down Expand Up @@ -733,19 +738,21 @@ export def create-catch-error-outside []: string -> string {

# Generate a fenced code block for output with a specific format.
export def create-fence-output []: string -> string {
# We use a combination of "\n" and (char nl) here for itermid script formatting aesthetics
# We use a combination of "\n" and (char nl) here for intermediate script formatting aesthetics
$"\"```\\n```output-numd\" | print(char nl)(char nl)($in)"
}

# Join a list of strings and generate a print statement for the combined output.
export def generate-print-lines []: list<string> -> string {
str join (char nl)
| escape-special-characters-and-quote
| $'($in) | print'
}

# Generate marker tags and code block delimiters for tracking output in the intermediate script.
export def generate-tags [
block_number: int
fence: string
block_number: int # index of the code block in the markdown
fence: string # the original fence line (e.g., '```nushell')
]: list<string> -> string {
let input = $in

Expand Down Expand Up @@ -792,9 +799,9 @@ export def modify-path [
| path join
}

# Create a backup of a file by moving it to a specified directory with a timestamp.
# Create a backup of a file by moving it to a subdirectory with a timestamp suffix.
export def create-file-backup [
file_path: path
file_path: path # path to the file to back up
]: nothing -> nothing {
$file_path
| if ($in | path exists) and ($in | path type) == 'file' {
Expand All @@ -803,12 +810,13 @@ export def create-file-backup [
}
}

#todo make config - an env record
# TODO: make config an env record

# Load numd configuration from a YAML file or command-line options into the environment.
export def --env load-config [
path: path # path to .yaml numd config file
--prepend_code: string
--table_width: int
path: path # path to a .yaml numd config file
--prepend_code: string # code to prepend to the intermediate script
--table_width: int # width for table output formatting
]: nothing -> nothing {
$env.numd = (
[
Expand All @@ -826,7 +834,7 @@ export def --env load-config [
} else { }
| where value != null
| if ($in | is-empty) { {} } else {
# if table_width or prepend code are set via parameters - they will have precendece
# if table_width or prepend code are set via parameters - they will have precedence
transpose --ignore-titles --as-record --header-row
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ The `generate-intermediate-script` command generates a script that contains code
let $intermediate_script_path = $file
| modify-path --prefix $'numd-temp-(generate-timestamp)' --suffix '.nu'

decortate-original-code-blocks $original_md_table
decorate-original-code-blocks $original_md_table
| generate-intermediate-script
| save -f $intermediate_script_path

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ $original_md_table | table -e --width 120 | table --width 120 | default '' | int
let $intermediate_script_path = $file
| modify-path --prefix $'numd-temp-(generate-timestamp)' --suffix '.nu'

decortate-original-code-blocks $original_md_table
decorate-original-code-blocks $original_md_table
| generate-intermediate-script
| save -f $intermediate_script_path

Expand All @@ -71,7 +71,7 @@ open $intermediate_script_path" | nu-highlight | print
let $intermediate_script_path = $file
| modify-path --prefix $'numd-temp-(generate-timestamp)' --suffix '.nu'

decortate-original-code-blocks $original_md_table
decorate-original-code-blocks $original_md_table
| generate-intermediate-script
| save -f $intermediate_script_path

Expand Down
8 changes: 4 additions & 4 deletions z_examples/4_book_working_with_lists/working_with_lists.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,9 +389,9 @@ Output:

```
# => ╭────────Zone────────┬───────Time───────╮
# => │ UTC │ 2025.12.10 20:16
# => │ CET │ 2025.12.10 21:16
# => │ Europe/Moscow │ 2025.12.10 23:16
# => │ Asia/Yekaterinburg │ 2025.12.11 01:16
# => │ UTC │ 2025.12.11 19:01
# => │ CET │ 2025.12.11 20:01
# => │ Europe/Moscow │ 2025.12.11 22:01
# => │ Asia/Yekaterinburg │ 2025.12.12 00:01
# => ╰────────Zone────────┴───────Time───────╯
```
3 changes: 1 addition & 2 deletions z_examples/6_edge_cases/error-with-try.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
# => : ^^^^^|^^^^^
# => : `-- Command `lssomething` not found
# => `----
# => help: `lssomething` is neither a Nushell built-in or a known external
# => command
# => help: `lssomething` is neither a Nushell built-in or a known external command
# =>
```
2 changes: 1 addition & 1 deletion z_examples/99_strip_markdown/numd_commands_explanations.nu
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $original_md_table | table -e --width 120
let $intermediate_script_path = $file
| modify-path --prefix $'numd-temp-(generate-timestamp)' --suffix '.nu'

decortate-original-code-blocks $original_md_table
decorate-original-code-blocks $original_md_table
| generate-intermediate-script
| save -f $intermediate_script_path

Expand Down
Loading