nushell / nushell.github.io

Nushell's main website, blog, book, and more
https://www.nushell.sh/book/
MIT License
183 stars 426 forks source link

`variable_not_found` when trying to access closure's span #922

Closed MrFoxPro closed 1 year ago

MrFoxPro commented 1 year ago

Describe the bug

I tried to make custom completer according to documentation and debug it:

let external_completer = {|spans|
  {
    $spans.0: { carapace $spans.0 nushell $spans | from json } # default
    nix: {
      with-env { NIX_GET_COMPLETIONS: ($spans | length | $in - 1) } {
        ^$"($spans.0)" ($spans | skip 1)
      }
      | lines
      | skip 1
      | str trim
      | parse -r '(?P<value>\S*)\s*(?P<description>.*)'
    }
  } | get $spans.0 | each {|it| do $it}
}
["test"] | do $external_completer

This result in error:

Error: nu::shell::variable_not_found

  × Variable not found
   ╭─[/home/foxpro/craft/foxpro-nix/test.nu:2:1]
 2 │   {
 3 │     $spans.0: { carapace $spans.0 nushell $spans | from json } # default
   ·     ───┬──
   ·        ╰── variable not found
 4 │     nix: {
   ╰────

Using this in config.nu results in lack of any completions. This is reproducable in 0.79.1, 0.80.0, 0.80.1

How to reproduce

Run this in Nushell

let external_completer = {|spans| print $in | print $spans }
["nix"] | do $external_completer

Expected behavior

$spans closure variable should be accessible

Screenshots

No response

Configuration

| key                | value                                                            |
| ------------------ | ---------------------------------------------------------------- |
| version            | 0.80.0                                                           |
| branch             | makepkg                                                          |
| commit_hash        | 8695b575848d5eb4d688087aa9e906b4d9e7c8d8                         |
| build_os           | linux-x86_64                                                     |
| build_target       | x86_64-unknown-linux-gnu                                         |
| rust_version       | rustc 1.69.0 (84c898d65 2023-04-16) (Arch Linux rust 1:1.69.0-3) |
| cargo_version      | cargo 1.69.0                                                     |
| build_time         | 2023-05-17 05:13:57 +00:00                                       |
| build_rust_channel | release                                                          |
| features           | default, zip                                                     |
| installed_plugins  |                                                                  |

Additional context

https://discord.com/channels/601130461678272522/1110138320404615168/1110176133820981258 No response

MrFoxPro commented 1 year ago

Oops, the problem was in do syntax I guess?... This one works

let external_completer = {| spans |
   { $spans.0: { carapace $spans.0 nushell $spans | from json } } | merge {
    nix: {
      let index = ($spans | length | $in - 1)
      if $index < 1 { } else {
      with-env { NIX_GET_COMPLETIONS: $index } {
        ^$"($spans.0)" ($spans | skip 1)
      }
      | lines
      | skip 1
      | str trim
      | parse -r '(?P<value>\S*)\s*(?P<description>.*)'
      }
    }
  } | get ($spans.0) | each {|it| do $it}
}

do $external_completer ["nix" "edit" ".#"]
amtoine commented 1 year ago

looks like we can close this maybe? :yum:

MrFoxPro commented 1 year ago

looks like we can close this maybe? yum

don't think so, at least provided examples on website are broken

amtoine commented 1 year ago

oooooh this is an example in the documentation, then yeah there is an issue with it :+1:

amtoine commented 1 year ago

@MrFoxPro i do not see the do $external_completer above in the book page, where does it come from?

*trying to see if that's a bug with Nushell or an out-of-date documentation :wink:

MrFoxPro commented 1 year ago

@amtoine My bad here, I didn't describe issue fully Basically, for make completions work, you usually perform steps:

  1. Look at docs, take example and add personal custom completions in config.nu:
    let external_completer = {|spans| 
    {
    $spans.0: { default_completer $spans | from json }
    "mycmd": { [[value, description]; ["compl1 ", "This is compl1"]; ["compl2 ", "This is compl2"]] }
    } | get $spans.0 | each {|it| do $it}
    }
  2. And this will make completions go away completely.
  3. You will try to debug this by running in script file or in CLI, so write it like this: 3.1

    let external_completer = {|spans| 
    {
    $spans.0: { default_completer $spans | from json }
    "mycmd": { [[value, description]; ["compl1 ", "This is compl1"]; ["compl2 ", "This is compl2"]] }
    } | get $spans.0 | each {|it| do $it}
    }
    ["mycmd" "compl1"] | do $external_completer

    it will result in unexpected error that I've described above. 3.2 Or like this:

    let external_completer = {|spans| 
    {
    $spans.0: { default_completer $spans | from json }
    "mycmd": { [[value, description]; ["compl1 ", "This is compl1"]; ["compl2 ", "This is compl2"]] }
    } | get $spans.0 | each {|it| do $it}
    }
    do $external_completer ["mycmd" "compl1"] 

    That will end up with an error:

    Error: nu::shell::not_a_list
    
    × Record field used twice
    ╭─[/home/foxpro/craft/foxpro-nix/test.nu:2:1]
    2 │   {
    3 │     $spans.0: { default_completer $spans | from json }
    ·     ────┬───
    ·         ╰── field first defined here
    4 │     "mycmd": { [[value, description]; ["compl1 ", "This is compl1"]; ["compl2 ", "This is compl2"]] }
    ·     ───┬───
    ·        ╰── field redefined here
    5 │   } | get $spans.0 | each {|it| do $it}
    ╰────

So I'm not sure if it's incorrect behaviour or outdated documentation.

amtoine commented 1 year ago

:question: what happens if you only take the default completion of the book without adding custom things?

:point_right: also is see there are a bunch of expected things here :yum:

Note as i do not have commands like default_completer, i'll simplify the test case

you are trying to run something like

let closure = {|argv|
  {
    $argv.0: "first arg"
    "arg0": "redefinition"
  } | get $argv.0 | each {|it| print $it}
}

do $closure ["arg0" "arg1"]

and i do indeed get

Error: nu::shell::not_a_list

  × Record field used twice
   ╭─[entry nushell/nushell#6:2:1]
 2 │   {
 3 │     $argv.0: "first arg"
   ·     ───┬───
   ·        ╰── field first defined here
 4 │     "arg0": "redefinition"
   ·     ───┬──
   ·        ╰── field redefined here
 5 │   } | get $argv.0 | each {|it| print $it}

here is what i see :relieved:

in the end this looks like an incorrect closure or arguments given to it? :thinking:

MrFoxPro commented 1 year ago

in the end this looks like an incorrect closure or arguments given to it? thinking

Yes, but this is how it's stated in example: image

amtoine commented 1 year ago

ooooh, yup then i wouldn't say the documentation is out-of-date but completely crazy :scream: :laughing:

this actually does not make any sense to me :sweat_smile:

amtoine commented 1 year ago

shall we transfer this to the website? and then try to find the proper form that this closure should take and finally fix the doc? :smirk: :muscle:

MrFoxPro commented 1 year ago

I'm newbie in Nushell and don't know how it should work in first place and if it is correct implementation