Modules

    Note! The current implementation of modules is quite bare-bones and will be expanded in the future. For example, it is not yet possible to import a module from within a module.

    A simple module can be defined like this:

    or in a file named the same as the the module you want to create:

    1. export def hello [name: string] {
    2. $"hello ($name)!"
    3. }
    4. export def hi [where: string] {
    5. $"hi ($where)!"
    6. }

    We defined hello and hi custom commands inside a greetings module.

    The export keyword makes it possible to later import the commands from the module.

    Similar to def, it is also possible to mark with the export keyword (you can learn more about def-env in the chapter).

    Using modules

    By itself, the module does not do anything. To use what the module exports, we need to it.

    1. > use greetings
    2. > greetings hello "world"
    3. hello world!
    4. > greetings hi "there"
    5. hi there!

    The hello and hi commands are now available with the greetings prefix.

    In general, anything after the use keyword forms an import pattern which controls how the symbols are imported. The import pattern can be one of the following:

    use greetings

    Imports all symbols with the module name as a prefix (we saw this in the previous example).

    The hello symbol will be imported directly without any prefix.

    use greetings [ hello, hi ]

    Imports multiple symbols directly without any prefix

    use greetings *

    You can also use the module name and the * glob to import all names directly without any prefix

    Module Files

    Nushell lets you implicitly treat a source file as a module. Let’s start by saving the body of the module definition into a file:

    1. # greetings.nu
    2. export def hello [name: string] {
    3. $"hello ($name)!"
    4. }
    5. export def hi [where: string] {
    6. $"hi ($where)!"
    7. }

    Now, you can call use directly on the file:

    Nushell automatically infers the module’s name from the stem of the file (“greetings” without the “.nu” extension). You can use any import patterns as described above with the file name instead of the module name.

    Any custom commands defined in a module without the export keyword will work only in the module’s scope:

    1. # greetings.nu
    2. export def hello [name: string] {
    3. }
    4. export def hi [where: string] {
    5. greetings-helper "hi" "there"
    6. }
    7. def greetings-helper [greeting: string, subject: string] {
    8. $"($greeting) ($subject)!"
    9. }

    Then, in Nushell we import all definitions from the “greetings.nu”:

    1. > use greetings.nu *
    2. > hello "world"
    3. hello world!
    4. > hi "there"
    5. hi there!
    6. > greetings-helper "foo" "bar" # fails because 'greetings-helper' is not exported

    Environment Variables

    So far we used modules just to import custom commands. It is possible to export environment variables the same way. The syntax is slightly different than what you might be used to from commands like let-env or :

    1. # greetings.nu
    2. export env MYNAME { "Arthur, King of the Britons" }
    3. export def hello [name: string] {
    4. $"hello ($name)"
    5. }

    You can notice we do not assign the value to MYNAME directly. Instead, we give it a block of code ({ ...}) that gets evaluated every time we call use. We can demonstrate this property, for example, with the command:

    1. > module roll { export env ROLL { random dice | into string } }
    2. > use roll ROLL
    3. > $env.ROLL
    4. 4
    5. > $env.ROLL
    6. 4
    7. > use roll ROLL
    8. > $env.ROLL
    9. 6
    10. 6

    As mentioned above, you can export definitions and environment variables from modules. This lets you more easily group related definitions together and export the ones you want to make public.

    You can also export aliases and externs, giving you a way to only use these features when you need. Exporting externs also gives you the ability to hide custom completion commands in a module, so they don’t have to be part of the global namespace.

    Here’s the full list of ways you can export:

    • export def - export a custom command
    • export def-env - export a custom environment command
    • export env - export an environment variable
    • export alias - export an alias
    • export extern - export a known external definition

    Hiding

    Any custom command, alias or environment variable, imported from a module or not, can be “hidden”, restoring the previous definition. (Note, it is not yet possible to export aliases from modules but they can still be hidden.) We do this with the command:

    1. > def foo [] { "foo" }
    2. > foo
    3. foo
    4. > hide foo
    5. > foo # error! command not found!

    The hide command also accepts import patterns, just like . The import pattern is interpreted slightly differently, though. It can be one of the following:

    hide foo or hide greetings

    • If the name is a custom command or an environment variable, hides it directly. Otherwise:
    • If the name is a module name, hides all of its exports prefixed with the module name

    hide greetings hello

    • Hides only the prefixed command / environment variable

    hide greetings [hello, hi]

    • Hides only the prefixed commands / environment variables

    hide greetings *

    • Hides all of the module’s exports, without the prefix

    Let’s show these with examples. We saw direct hiding of a custom command already. Let’s try environment variables:

    1. > let-env FOO = "FOO"
    2. > $env.FOO
    3. FOO
    4. > hide FOO
    5. > $env.FOO # error! environment variable not found!

    And finally, when the name is the module name (assuming the previous greetings module):

    1. > use greetings.nu
    2. > $env."greetings MYNAME"
    3. Arthur, King of the Britons
    4. > greetings hello "world"
    5. hello world!
    6. > hide greetings
    7. > $env."greetings MYNAME" # error! environment variable not found!
    8. > greetings hello "world" # error! command not found!