Search

Dark theme | Light theme

May 10, 2025

Nushell Niceties: Reload Environment

With the command config nu you can change the Nushell configuration. In order to enable any changes you made in the current shell session you must run source $nu.config-path. This will load the configuration in the current shell session. Another option is of course to stop the current shell session and start a new one.

Written with Nushell 0.104.0.

April 26, 2025

Nushell Niceties: Using Request Headers With HTTP Commands

The nice thing about the http command in Nushell is that you can interact with HTTP endpoints without the need to install any external tools. You can use several subcommands like get, post, put, delete and patch. Each of these commands has the options to specify request headers. You can use the option --headers or the short version -H followed by a list of header keys and values.

In the following example you can see how to use the --headers option to specify the request headers:

# Use the --headers option to specify the request headers.
# The headers are specified as a list of header keys and values.
http get --headers [Accept application/json] https://httpbin.org/headers

Instead of specifying the headers in the command you can also create a variable with list of header keys and values:

# Create a variable with a list of header keys and values.
const headers = [
    Accept application/json
    Origin https://mrhaki.com
    Access-Control-Request-Method GET
    Access-Control-Request-Headers content-type
]

# Use the variable with the http get command.
# In this case the short version -H is used.
http get -H $headers https://httpbin.org/headers

Written with Nushell 0.103.0.

April 25, 2025

Nushell Niceties: Posting JSON to an HTTP Endpoint

The http command in Nushell can be used to interact with HTTP endpoints. You can post data to an endpoint using the post subcommand. If you want to post JSON data than you can simply use a record data structure and use the argument --content-type application/json (or the shorthand -t application/json). Nushell will automatically convert the record data structure to JSON and use it as the body of the HTTP request.

In the following example we post a record data structure to the https://httpbin.org/anything endpoint. The record data structure is defined as last argument after the URL:

# You can post JSON data to an endpoint.
# To indicate the content type is JSON
# you can use the --content-type application/json argument.
# After the URL you can specify the data to post
# using a record data structure.
http post --content-type application/json https://httpbin.org/anything {
    name: mrhaki,
    age: 51,
    city: Tilburg
}

The record data structure can be created with variables and commands:

# You can use variables and command in the record data structure.
const username = 'mrhaki'
const firstName = 'Hubert'
const keyLastName = 'lastName'

http post --content-type application/json --full https://httpbin.org/anything {
    name: $username,
    firstName: ($firstName | str downcase),
    $keyLastName: 'Klein Ikkink'
}

Instead of defining the data directly in the http post command you can also create the record data structure first and then pass it to the http post command as last argument:

# The record data structure can be created first and
# then passed to the http post command as last argument.
const data = {
    os: 'MacOS',
    shells: ['Nushell', 'PowerShell']
}

http post --content-type application/json https://httpbin.org/anything $data

You can also use input redirection to pass the record data structure to the http post command. In the following example we pass a record data structure to the http post command using input redirection:

# You can pipe the record data structure to the http post command.
{ username: 'mrhaki' } | http post --content-type application/json https://httpbin.org/anything

Instead of defining the record structure directly as input you can also use the content of a file with JSON data:

# You can read the content of a file with JSON data and
# pass it to the http post command as input using pipes.
{ username: 'mrhaki' } | save data.json
open --raw data.json | http post --content-type application/json https://httpbin.org/anything

As a matter of fact you can use any command that outputs JSON as input to the http post command:

# You can use any command that outputs JSON
# as input to the http post command.
def createJSON [] {
    { username: 'mrhaki' }
}
createJSON | http post --content-type application/json https://httpbin.org/anything

Written with Nushell 0.103.0.

March 21, 2025

Nushell Niceties: Open File With Associated Application

To look at the contents of a file you can use the open command in Nushell. But if we want to open a file with an associated application you must use the start command. For example if you have an HTML file and use the open command you see the HTML source. When you use the start command it opens the HTML file in your default browser.

You can also use the start command to open a directory in the file manager of your operating system. If you use MacOS and type start . it will open the current directory in the Finder application.

When you use the start command followed by a URL it will open the URL in your default browser.

Written with Nushell 0.103.0.

March 18, 2025

SDKMAN! Listing And Upgrading Outdated SDKs And Tools

SDKMAN! is as powerful tool to install and manage software development kits (SDKs) and tools, like Java, Groovy, Gradle, Maven, Spring Boot and Quarkus. If you want to see if a new version of a SDK or tool is available, you can use the sdk upgrade command. This command will list all outdated SDKs and tools. The installed version and the latest version are shown for each SDK and tool. To see if a single SDK or tool is outdated, you can use the name of the SDK or tool as argument to the sdk upgrade command.

In the following example you see the output of a sdk upgrade command for the Spring Boot tool. By answering Y (default answer) to the question Use prescribed default version(s)? you can upgrade the Spring Boot tool to the latest version:

$ sdk upgrade springboot

Available defaults:
springboot (local: 3.1.5, 3.2.4; default: 3.4.3)

Use prescribed default version(s)? (Y/n):

Downloading: springboot 3.4.3

In progress...

####################################################################### 100.0%

Installing: springboot 3.4.3
Done installing!


Setting springboot 3.4.3 as default.
$

You can also run sdk upgrade without an argument and the output shows all SDKs and tools that are outdated. You can upgrade all outdated SDKs and tools by answering Y to the question Use prescribed default version(s)?. In the following example you see the output of a sdk upgrade command without an argument:

$ sdk upgrade

Available defaults:
groovy (local: 4.0.25, 4.0.24, 4.0.23, 3.0.22, 4.0.20; default: 4.0.26)
java (local: 20-tem, 21-tem, 11.0.22-tem, 23-tem, 11.0.25-tem, 21-zulu, 19.0.2-tem, 19.0.1-tem, 17.0.10-tem, 17.0.13-tem, 11.0.8.hs-adpt, 23-graalce, 8.0.432-tem, 21.0.1-tem, 21.0.3-tem, 21.0.2-tem, 21.0.5-tem, 21.0.4-tem; default: 21.0.6-tem)

Use prescribed default version(s)? (Y/n):

Downloading: groovy 4.0.26

In progress...

####################################################################### 100.0%

Installing: groovy 4.0.26
Done installing!


Setting groovy 4.0.26 as default.

Downloading: java 21.0.6-tem

In progress...

####################################################################### 100.0%

Repackaging Java 21.0.6-tem...
Restored java version to 21.0.4-tem (default)

Using java version 11.0.25-tem in this shell.

Done repackaging...
Cleaning up residual files...

Installing: java 21.0.6-tem
Done installing!


Setting java 21.0.6-tem as default.
$

Written with SKDMAN! 5.19.0.

March 14, 2025

Nushell Niceties: Getting The HTTP Response Status

Nushell has a built-in command to invoke HTTP requests: http. You don’t need an external tool like curl or httpie to make HTTP requests. There a lot of options to use with the http command. One of them is the --full or shorter -f option to return a table with extra details of the HTTP request and response. The request and response headers, the body and status are returned in the table. You can easily get information from the table with all the default selection options for a table structure.

In the following example you see the table structure that is returned for a http get request with and without the --full option:

> http get https://www.mrhaki.com/nushell.txt # Without --full you get only the response body.
Nushell rocks!
> http get --full https://www.mrhaki.com/nushell.txt # Use --full to get the full response.
╭─────────┬────────────────────────────────────────────────────────────────────────────────────────────╮
│         │ ╭──────────┬─────────────────────────────────────────────────────────────────────────────╮ │
│ headers │ │ request  │ [list 0 items]                                                              │ │
│         │ │          │ ╭────┬───────────────────────────┬────────────────────────────────────────╮ │ │
│         │ │ response │ │  # │           name            │                 value                  │ │ │
│         │ │          │ ├────┼───────────────────────────┼────────────────────────────────────────┤ │ │
│         │ │          │ │  0 │ age                       │ 51                                     │ │ │
│         │ │          │ │  1 │ cache-status              │ "Netlify Edge"; hit                    │ │ │
│         │ │          │ │  2 │ cache-control             │ public,max-age=0,must-revalidate       │ │ │
│         │ │          │ │  3 │ content-type              │ text/plain; charset=UTF-8              │ │ │
│         │ │          │ │  4 │ content-length            │ 14                                     │ │ │
│         │ │          │ │  5 │ x-nf-request-id           │ 01JP9NJNTBY60HF0TR8X2R3J0K             │ │ │
│         │ │          │ │  6 │ server                    │ Netlify                                │ │ │
│         │ │          │ │  7 │ etag                      │ "010320ca2351da56022222fa858c94ae-ssl" │ │ │
│         │ │          │ │  8 │ accept-ranges             │ bytes                                  │ │ │
│         │ │          │ │  9 │ strict-transport-security │ max-age=31536000                       │ │ │
│         │ │          │ │ 10 │ date                      │ Fri, 14 Mar 2025 06:31:00 GMT          │ │ │
│         │ │          │ ╰────┴───────────────────────────┴────────────────────────────────────────╯ │ │
│         │ ╰──────────┴─────────────────────────────────────────────────────────────────────────────╯ │
│ body    │ Nushell rocks!                                                                             │
│ status  │ 200                                                                                        │
╰─────────┴────────────────────────────────────────────────────────────────────────────────────────────╯
>

To get the response status you can retrieve the value from the status field that is in the table:

# With the --full option a table is returned by http get with the fields
# headers, body and status.

# Using get to get the value of the status field.
assert equal (http get --full https://www.mrhaki.com/nushell.txt | get status) 200

# Using select to get a record with the result.
assert equal (http get -f https://www.mrhaki.com/nushell.txt | select status) {status: 200}

Written with Nushell 0.102.0.

March 11, 2025

Nushell Niceties: Trimming Strings

Nushell has some powerful commands to work with strings. The str trim command can be used to trim whitespace from a string. By default whitespace from the beginning and end of a string is removed. To only remove whitespace from the beginning of the string you can use the --left argument (or the shorter option -l). For removing whitespace from the end of the string you can use the option --right or the shorter option -r. To trim a string based on another character you can use the option --char or the shorter option -c followed by the character to trim.

In the following example you can see how the str trim command can be used to remove whitespace:

use std/assert

# str trim removes whitespace from the beginning and end of the string
assert equal (' mrhaki ' | str trim) 'mrhaki'

# Use --left or -l to only remove whitespace from the left.
assert equal (' mrhaki ' | str trim --left) 'mrhaki '

# Use --right or -r to only remove whitespace from the right.
assert equal (' mrhaki ' | str trim --right) ' mrhaki'

# With double quoted strings sr trim removes not
# only spaces, but also other characters like \t and \n.
assert equal ("\tmrhaki\n" | str trim) 'mrhaki'
assert equal ("\t mrhaki \n" | str trim) 'mrhaki'

You can use the argument --char or -c to specify another character to use for trimming:

use std/assert

# The str trim command with the --char or -c argument
# to specify a character to trim.
assert equal ('**mrhaki**' | str trim --char '*') 'mrhaki'
assert equal ('* mrhaki *' | str trim -c '*') ' mrhaki '

You can specify the name of keys of a record to trim the values of those keys:

use std/assert

# The str trim command accepts names of keys to
# trim the values of those keys in a record.
let user = {
    name: 'Hubert Klein Ikkink ',
    alias: ' mrhaki '
} | str trim name alias

assert equal $user {
    name: 'Hubert Klein Ikkink',
    alias: 'mrhaki'
}

The str trim command can be applied to lists to trim each element as you can see in the next example:

use std/assert

# The str trim command can be applied to lists
# to trim each element.
let shells = [' NuShell', 'Powershell '] | str trim
assert equal $shells ['NuShell', 'Powershell']

Finally the str trim command can be used to trim the values in one or more columns in a table:

use std/assert

# The str trim command also accepts names of columns for a table.
# The values in the column are trimmed.
let users = [
    [name alias];
    ['Hubert Klein Ikkink ' 'mrhaki ']
] | str trim --right alias

# Name column is not transformed.
assert equal $users.0.name 'Hubert Klein Ikkink '
# Alias column is transformed.
assert equal $users.0.alias 'mrhaki'

Written with Nushell 0.102.0.

March 2, 2025

Nushell Niceties: Getting The Current Version Of Nushell

The version command can be used to get the current version of Nushell. The result is a record structure with different keys with information about the Nushell version. For example the property version contains the current version of Nushell, the properties major, minor and patch contain the major, minor and patch version of Nushell.

The version command accepts the argument check to check if a newer version of Nushell is available. The returned record structure contains the property current with a value true or false depending on whether a newer version is available. The version check command also return the latest version as value of the property latest.

In the following example you see output of the version command:

> version
╭────────────────────┬────────────────────────────────────────────────╮
│ version            │ 0.102.0                                        │
│ major              │ 0                                              │
│ minor              │ 102                                            │
│ patch              │ 0                                              │
│ branch             │                                                │
│ commit_hash        │                                                │
│ build_os           │ macos-x86_64                                   │
│ build_target       │ x86_64-apple-darwin                            │
│ rust_version       │ rustc 1.84.1 (e71f9a9a9 2025-01-27) (Homebrew) │
│ cargo_version      │ cargo 1.84.1                                   │
│ build_time         │ 2025-02-04 15:49:35 +00:00                     │
│ build_rust_channel │ release                                        │
│ allocator          │ mimalloc                                       │
│ features           │ default, sqlite, trash                         │
│ installed_plugins  │                                                │
╰────────────────────┴────────────────────────────────────────────────╯

You can also use all record navigation options to get specific information from the version command output:

> version | get version
0.102.0
> version | get features
default, sqlist, trash

The following example output of the version check command shows the latest version of Nushell is used:

> version check
╭─────────┬─────────╮
│ channel │ release │
│ current │ true    │
│ latest  │ 0.102.0 │
╰─────────┴─────────╯

The following example uses the if command to check if the current version of Nushell is the latest version:

# Check if the current property of version check is true.
> if (version check).current {
    let v = version
    print $'You are using the latest version of Nushell -> ($v.version)'
}
You are using the latest version of Nushell -> 0.102.0

Written with Nushell 0.102.0.

February 27, 2025

Nushell Niceties: Converting Strings To Kebab Case

Nushell has a lot of commands to work with strings. The str kebab-case command can be used to convert a string to kebab case. Kebab-case is a string that contains only lowercase letters and words are separated by hyphens.

In the following example you can see how to use the str kebab-case command for a string value:

# Add assertion support.
use std/assert

# Different examples of string types that are transformed to kebab-case.
assert equal ('stringInCamelCase' | str kebab-case) 'string-in-camel-case'
assert equal ('string_with_underscores' | str kebab-case) 'string-with-underscores'
assert equal ('StringInPascalCase' | str kebab-case) 'string-in-pascal-case'
assert equal ('string with spaces' | str kebab-case) 'string-with-spaces'
assert equal ('STRING-WITH-UPCASE' | str kebab-case) 'string-with-upcase'

# Special characters are removed.
assert equal ('Nushell rocks!' | str kebab-case) 'nushell-rocks'

The str kebab-case command accepts as extra argument one or more names of keys in a record. The values of these keys are transformed to kebab-case as you can see in the following example:

use std/assert

# The str kebab-case command accepts names of keys to
# transform the values to kebab-case in a record.
let user = {
    name: 'Hubert Klein Ikkink',
    alias: 'MrHaki'
} | str kebab-case name alias

assert equal $user {
    name: 'hubert-klein-ikkink',
    alias: 'mr-haki'
}

The str kebab-case command can be applied to lists to transform each element to kebab-case:

use std/assert

# The str kebab-case command can be applied to lists
# to transform each element to kebab-case.
let shells = ['Nushell' 'PowerShell'] | str kebab-case
assert equal $shells ['nushell' 'power-shell']

Finally the str kebab-case command can be used to transform the values in a column to kebab-case. The names of the columns must be passed as extra arguments to the str kebab-case command:

use std/assert

# The str kebab-case command also accepts names of columns for a table.
# The values in the column are transformed to kebab-case.
let users = [
    [name alias];
    ['Hubert Klein Ikkink' 'MrHaki']
] | str kebab-case alias

# Values in the alias column are transformed into kebab-case.
assert equal $users.alias ['mr-haki']
# Values in the name column are not changed.
assert equal $users.name ['Hubert Klein Ikkink']
# Assertion for complete table.
assert equal $users [[name alias]; ['Hubert Klein Ikkink' 'mr-haki']]

Written with Nushell 0.102.0.

February 20, 2025

Helidon SE Helpings: Serving Observe Endpoints On Different Port

When you enable the /observe endpoints you can configure them to be served on a different port than the application. By default the endpoints are available on the same port as the application. But you can define an extra named socket with another port number in the configuration of the WebServer instance. And in the configuration of the ObserveFeature instance you can define the socket name that should be used for the observe endpoints.

You can use configuration properties or code to configure the extra socket.

Using configuration

In the following example configuration properties file you see how to configure the extra socket and the observe feature to use the extra socket. A new socket with the name observe is defined and port 8081 is used by defining the property prefixed with server.sockets. The value is a list so you have to use a list definition for the property names name and port. Next this socket is used in the configuration of the observe feature by assigning the name to the server.features.observe.sockets property.

# File: application.properties
...
# Configure new socket for observe endpoints.
# Set the name of the new socket to observe.
server.sockets.0.name=observe
# Set the port for the new socket to 8081.
server.sockets.0.port=8081

# Configure the observe feature to use the observe socket.
server.features.observe.sockets.0=observe

# Set port for default socket.
server.port=8080
...

In your application code you can use the configuration to create a WebServer instance:

// File: Main.java
...
import io.helidon.config.Config;
import io.helidon.webserver.WebServer;
...
  public static void main(String[] args) {
    ...
    Config config = Config.create();

    WebServer server =
        WebServer.builder()
            ...
            // Read configuration properties.
            .config(config.get("server"))
            .build()
            .start();
  }
...

Using application code

Alternatively you can write the configuration in your application code. In the following example you can see how to create a WebServer instance using the configuration. To add a new socket definition you can use the WebServer.Builder.putSocket() method. Next you can use the ObserveFeature.Builder.sockets() method to connect the observe feature to the new socket.

// File: Main.java
...
import io.helidon.webserver.observe.ObserveFeature;
import io.helidon.webserver.observe.health.HealthObserver;
import io.helidon.webserver.WebServer;
...
  public static void main(String[] args) {
    ...
    // Create health check observer and enable details.
    HealthObserver healthObserver =
        HealthObserver.builder()
            // Show details in health endpoint.
            .details(true)
            .build();

    WebServer server =
        WebServer.builder()
            ...
            // Set default port.
            .port(8080)
            // Create a new socket with name "observe"
            // to run on port 8081.
            .putSocket("observe", socket -> socket.port(8081))
            .addFeature(
                ObserveFeature.builder()
                    // Set name of socket as defined in the WebServer builder.
                    // This will enable the /observe endpoints on port 8081.
                    .sockets(List.of("observe"))
                    .addObserver(healthObserver)
                    .build())
            .build()
            .start();
  }
...

When you start your application you must use port 8081 to access /observe endpoints.

$ curl -X GET http://localhost:8081/observe/health | jq -r .
{
  "status": "UP",
  "checks": []
}
$

Written with Helidon 4.1.6.