Home Explore Blog CI



nushell

1st chunk of `cookbook/input_listen_keys.md`
86f377c4c95ba0dde30bfa9118b4fd7e235cfd549a339ebb0000000100000bb3
---
title: Acting on keypresses using `input listen`
---

# Acting on keypresses using `input listen`

A common "key listening" pattern is to:

- Listen for a specific key (or one of a set of keys) to be pressed
- Take action depending on which key was pressed
- Loop if one of the expected keys wasn't pressed

There are several patterns that can accomplish this, each with advantages and disadvantages. You can choose from one of the following patterns that best fits your use-case and coding style:

1.  A first attempt might be the following simple loop. This will work for some cases, but a `loop` cannot itself return a _value_:

    ```nu
    def run_some_code [] {
      print "I'm running the code, but I can't return a"
      print "value because I need to `break` out of the loop."
      42
      break
    }

    print '(a) Run some code (x) Exit'

    loop {
      let key = (input listen --types [key])
      if ($key.code == 'a') and ($key.modifiers == []) {
          run_some_code
      } else if ($key.code == 'x') and ($key.modifiers == []) {
          print 'User exited'
          break
      } else if ($key.code == 'c') and ($key.modifiers == ['keymodifiers(control)']) {
          print 'Terminated with Ctrl-C'
          break
      } else {
          print "That key wasn't recognized."
          print 'Press (a) to run some code or (x) to Exit'
          continue
      }
    }
    ```

2.  If you need to return a value, you can use a mutable variable to hold the key result after the input loop has ended, _then_ return a value based on the captured keypress:

    ```nu
    def run_some_code [] {
      print "I'm running the code and returning 42"
      42
    }

    mut key_props = []
    print '(a) Run some code (x) Exit'

    loop {
      let key = (input listen --types [key])
      $key_props = [$key.code $key.modifiers]
      let valid_keys = [
        [ 'a' [] ]
        [ 'x' [] ]
        [ 'c' ['keymodifiers(control)'] ]
      ]

      if $key_props in $valid_keys {
          break
      } else {
          print "That key wasn't recognized."
          print 'Press (a) to run some code or (x) to Exit'
          continue
      }
    }

    # Act on the captured keypress from the mutable variable
    if $key_props == [ 'a' [] ] {
        run_some_code
    } else if $key_props == [ 'x' [] ] {
        print 'User exited'
    } else if $key_props == [ 'c' ['keymodifiers(control)'] ] {
        print 'Terminated with Ctrl-C'
    }
    ```

3.  This version uses a custom command that recursively calls itself until one of the desired keys is pressed. However, keep in mind that Nushell limits the number of recursive calls based on the value of `$env.config.recursion_limit` (default 50). Hold down the <kbd>y</kbd> key (not monitored) to demonstrate an early exit based on recursion limits.

    Note that `break` statements are not needed in this version.

    ```nu
    def run_some_code [] {
      print "I'm running the code and returning 42"

Title: Acting on Keypresses with `input listen`
Summary
The document describes different patterns for listening to keypresses in Nushell using the `input listen` command. It presents three approaches: a simple loop (which cannot return a value), using a mutable variable to store the key result, and a recursive custom command. Each pattern has its own advantages and disadvantages for capturing user input and taking action based on the key pressed.