diff --git a/README.md b/README.md index eb26822..40e98c5 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ ![dotnu](https://github.com/user-attachments/assets/4fb74e46-f75b-4155-8e61-8ff75db66117) -

dotnu - tools for Nushell module developers ๐Ÿ› ๏ธ

+

dotnu - tools for Nushell module developers

(A good companion for numd)

dotnu augments Nushell with helpers for literate programming, dependency analysis, and script profiling.

-## dotnu video demo +## Video demo dotnu demo @@ -22,6 +22,7 @@ use dotnu ``` ### [`nupm`](https://github.com/nushell/nupm) + ```nushell no-run nupm install https://github.com/nushell-prophet/dotnu --git # if nupm modules are not in `NU_LIB_DIRS`: @@ -30,15 +31,15 @@ $env.NU_LIB_DIRS ++= [ ($env.NUPM_HOME | path join "modules") ] use dotnu ``` -## Embeds โ€” keeping examples in sync +## Embeds โ€” Literate Programming `dotnu` lets you write **literate Nushell**: ordinary Nushell scripts that include the real command output right after each pipeline ending in `| print $in`. See the [capture example](/dotnu-capture.nu) to grasp the idea quickly. The `| print $in` suffix acts as a simple `print` in native Nushell and as a capture marker for dotnu, so scripts remain valid and functional even when run without loading the `dotnu` module. -The main command is `dotnu embeds-update`. +### `dotnu embeds-update` -`dotnu embeds-update` takes a script, rewrites every `print $in` line so its output is easy to parse, runs the modified script, captures what each marked line prints, and then replaces the old `# =>` blocks in the original file with the fresh output. +The main command. It takes a script, rewrites every `print $in` line so its output is easy to parse, runs the modified script, captures what each marked line prints, and then replaces the old `# =>` blocks in the original file with the fresh output. You can run it on a file path (e.g., `dotnu embeds-update dotnu-capture.nu`) or pipe a script into it (e.g., `"ls | print $in" | dotnu embeds-update`). @@ -69,15 +70,15 @@ dotnu embeds-update --help # => ``` -### Embeds helper commands +### Helper commands -While it is easy to write scripts in editor, there are several convenience helper commands that facilitate populating script files from terminal. +While it is easy to write scripts in an editor, there are several convenience helper commands that facilitate populating script files from the terminal. -### `dotnu embeds-setup` +#### `dotnu embeds-setup` -define or change the capture file (add `--auto-commit` to autoโ€‘commit snapshots). +Define or change the capture file (add `--auto-commit` to auto-commit snapshots). -```nu +```nushell dotnu embeds-setup --help # => Set environment variables to operate with embeds # => @@ -100,11 +101,11 @@ dotnu embeds-setup --help # => ``` -### `dotnu embeds-capture-start` and `dotnu embeds-capture-stop` +#### `dotnu embeds-capture-start` and `dotnu embeds-capture-stop` -record every result printed in the interactive session. +Record every result printed in the interactive session. -```nu +```nushell dotnu embeds-capture-start --help # => start capturing commands and their outputs into a file # => @@ -126,11 +127,11 @@ dotnu embeds-capture-start --help # => ``` -### `dotnu embed-add` +#### `dotnu embed-add` -capture only the pipeline you run it on; useful for fineโ€‘grained examples. +Capture only the pipeline you run it on; useful for fine-grained examples. -```nu +```nushell dotnu embed-add --help # => Embed stdin together with its command into the file # => @@ -152,11 +153,11 @@ dotnu embed-add --help # => ``` -### `dotnu embeds-remove` +#### `dotnu embeds-remove` -strip all captured output, leaving clean code. +Strip all captured output, leaving clean code. -```nu +```nushell dotnu embeds-remove --help # => Removes annotation lines starting with "# => " from the script # => @@ -175,9 +176,9 @@ dotnu embeds-remove --help # => ``` -## Commands +## Dependency Analysis -### dotnu dependencies +### `dotnu dependencies` ```nushell dotnu dependencies --help @@ -218,7 +219,7 @@ dotnu dependencies --help # => ``` -### dotnu filter-commands-with-no-tests +### `dotnu filter-commands-with-no-tests` ```nushell dotnu filter-commands-with-no-tests --help @@ -251,11 +252,46 @@ dotnu filter-commands-with-no-tests --help # => ``` -### dotnu set-x +## Script Profiling + +### `dotnu set-x` + +Divide a script into blocks and generate a new script that prints each block before executing it, along with timing information. -`dotnu set-x` opens a regular .nu script. It divides it into blocks using the specified regex (by default, it is "\n\n") and generates a new script that will print the code of each block before executing it, along with the timings of each block's execution. +```nushell +dotnu set-x --help +# => Open a regular .nu script. Divide it into blocks by "\n\n". Generate a new script +# => that will print the code of each block before executing it, and print the timings of each block's execution. +# => +# => Usage: +# => > set-x {flags} +# => +# => Flags: +# => -h, --help: Display the help message for this command +# => --regex : regex to split on blocks (default: '\n+\n' - blank lines) +# => --echo: output script to terminal +# => --quiet: don't print any messages +# => +# => Parameters: +# => file : path to `.nu` file +# => +# => Input/output types: +# => โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +# => โ”‚ # โ”‚ input โ”‚ output โ”‚ +# => โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# => โ”‚ 0 โ”‚ any โ”‚ any โ”‚ +# => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +# => +# => Examples: +# => +# => > set-x tests/assets/set-x-demo.nu --echo | lines | first 3 | to text +# => mut $prev_ts = ( date now ) +# => print ("> sleep 0.5sec" | nu-highlight) +# => sleep 0.5sec +# => +``` -Let's check the code of the simple `set-x-demo.nu` script +Example with a simple script: ```nushell let $filename = [tests assets set-x-demo.nu] | path join @@ -269,8 +305,6 @@ open $filename | lines | table -i false # => โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ ``` -Let's see how `dotnu set-x` will modify this script - ```nushell dotnu set-x $filename --echo | lines | table -i false # => โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ @@ -292,3 +326,124 @@ dotnu set-x $filename --echo | lines | table -i false # => โ”‚ โ”‚ # => โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ ``` + +## Utilities + +### `dotnu generate-numd` + +Pipe a `.nu` script into this command to convert it into `.numd` format (markdown with code blocks). + +```nushell +dotnu generate-numd --help +# => Generate `.numd` from `.nu` divided into blocks by "\n\n" +# => +# => Usage: +# => > generate-numd +# => +# => Flags: +# => -h, --help: Display the help message for this command +# => +# => Input/output types: +# => โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +# => โ”‚ # โ”‚ input โ”‚ output โ”‚ +# => โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# => โ”‚ 0 โ”‚ any โ”‚ any โ”‚ +# => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +# => +``` + +```nushell +"sleep 0.5sec\n\nsleep 0.7sec" | dotnu generate-numd +# => ```nu +# => sleep 0.5sec +# => ``` +# => +# => ```nu +# => sleep 0.7sec +# => ``` +# => +``` + +### `dotnu extract-command-code` + +Extract a command from a module, resolve its parameter defaults, and create a standalone script you can source to get all variables in scope. Useful for debugging. + +```nushell +dotnu extract-command-code --help +# => Extract command code from a module and save it as a `.nu` file that can be sourced. +# => By executing this `.nu` file, you'll have all the variables in your environment for debugging or development. +# => +# => Usage: +# => > extract-command-code {flags} <$module_path> <$command> +# => +# => Flags: +# => -h, --help: Display the help message for this command +# => --output : a file path to save the extracted command script +# => --clear-vars: clear variables previously set in the extracted .nu file +# => --echo: output the command to the terminal +# => --set-vars : set variables for a command (default: {}) +# => --code-editor : code is my editor of choice to open the result file (default: 'code') +# => +# => Parameters: +# => $module_path : path to a Nushell module file +# => $command : the name of the command to extract +# => +# => Input/output types: +# => โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +# => โ”‚ # โ”‚ input โ”‚ output โ”‚ +# => โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# => โ”‚ 0 โ”‚ any โ”‚ any โ”‚ +# => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +# => +``` + +### `dotnu list-exported-commands` + +List commands defined in a module file. Use `--export` to show only exported commands. + +```nushell +dotnu list-exported-commands --help +# => Usage: +# => > list-exported-commands {flags} <$path> +# => +# => Flags: +# => -h, --help: Display the help message for this command +# => --export: use only commands that are exported +# => +# => Parameters: +# => $path +# => +# => Input/output types: +# => โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +# => โ”‚ # โ”‚ input โ”‚ output โ”‚ +# => โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# => โ”‚ 0 โ”‚ any โ”‚ any โ”‚ +# => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +# => +``` + +### `dotnu module-commands-code-to-record` + +Extract all commands from a module file and return them as a record where keys are command names and values are their source code. + +```nushell +dotnu module-commands-code-to-record --help +# => Extract all commands from a module as a record of {command_name: source_code} +# => +# => Usage: +# => > module-commands-code-to-record +# => +# => Flags: +# => -h, --help: Display the help message for this command +# => +# => Parameters: +# => module_path : path to a Nushell module file +# => +# => Input/output types: +# => โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ +# => โ”‚ # โ”‚ input โ”‚ output โ”‚ +# => โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +# => โ”‚ 0 โ”‚ any โ”‚ any โ”‚ +# => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ +# => +``` diff --git a/dotnu/commands.nu b/dotnu/commands.nu index e712631..cea43b9 100644 --- a/dotnu/commands.nu +++ b/dotnu/commands.nu @@ -60,10 +60,11 @@ sleep 0.5sec ' export def 'set-x' [ file: path # path to `.nu` file - --regex: string = "\n+\n" # regex to use to split .nu on blocks + --regex: string # regex to split on blocks (default: '\n+\n' - blank lines) --echo # output script to terminal --quiet # don't print any messages ] { + let regex = $regex | default "\n+\n" let out_file = $file | str replace -r '(\.nu)?$' '_setx.nu' open $file @@ -91,14 +92,14 @@ export def 'set-x' [ } } -# Generate `.numd` from `.nu` divided on blocks by "\n\n" +# Generate `.numd` from `.nu` divided into blocks by "\n\n" export def 'generate-numd' [] { split row -r "\n+\n" | each { $"```nu\n($in)\n```\n" } | to text } -# Extract a command code from a module and save it as a `.nu` file that can be sourced. +# Extract command code from a module and save it as a `.nu` file that can be sourced. # By executing this `.nu` file, you'll have all the variables in your environment for debugging or development. export def 'extract-command-code' [ $module_path: path # path to a Nushell module file @@ -155,7 +156,7 @@ export def 'extract-command-code' [ } } -# todo: `list-exported-commands` should be a completion for nushell cli +# todo: `list-exported-commands` should be a completion for Nushell CLI export def 'list-exported-commands' [ $path: path @@ -179,7 +180,7 @@ export def 'list-exported-commands' [ } else { } } -#todo: make configuration like --autocommit in file itself +# todo: make configuration like --autocommit in file itself # Inserts captured output back into the script at capture points export def 'embeds-update' [ @@ -337,7 +338,7 @@ export def --env 'embeds-capture-stop' []: nothing -> nothing { } #### helpers -# they used to be separately here from the main code, but I want to experiment with structure +# they used to be separate from the main code, but I want to experiment with structure # so all the commands are in one file now, and all are exported, to be available in my scripts # that can use this file commands with 'use ..', though main commands are exported in mod.nu @@ -386,7 +387,7 @@ export def check-clean-working-tree [ } } -# make a record from code with variable definitions +# Make a record from code with variable definitions @example '' { "let $quiet = false; let no_timestamp = false" | variable-definitions-to-record } --result {quiet: false no_timestamp: false} @@ -561,7 +562,7 @@ export def list-module-commands [ $calls | append $defs_without_calls } -# Extract the specified command and all its dependencies, outputting them to stdout +# Extract all commands from a module as a record of {command_name: source_code} export def 'module-commands-code-to-record' [ module_path: path # path to a Nushell module file ] { @@ -709,7 +710,7 @@ export def 'comment-hash-colon' [ } } -# Extracts captured output from a script file execution result +# Extract captured output from a script file execution results export def execute-and-parse-results [ script: string --script_path: path diff --git a/tests/assets/dotnu-capture-updated.nu b/tests/assets/dotnu-capture-updated.nu index 2f4ee77..ba29e9e 100644 --- a/tests/assets/dotnu-capture-updated.nu +++ b/tests/assets/dotnu-capture-updated.nu @@ -15,7 +15,7 @@ ls | sort-by modified -r | last 2 | print $in # => โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ random int | print $in -# => 4577019228065240114 +# => 315585275042786947 'Say hello to the core team of the Nushell' | str replace 'Nushell' 'Best shell'