Nushell
安装 Nu !
快速开始
  • Nushell 之书
  • 命令参考列表
  • 实战指南
  • 语言参考指南
  • 贡献指南
博客
  • English
  • 中文
  • Deutsch
  • Français
  • Español
  • 日本語
  • Português do Brasil
  • Русский язык
GitHub
安装 Nu !
快速开始
  • Nushell 之书
  • 命令参考列表
  • 实战指南
  • 语言参考指南
  • 贡献指南
博客
  • English
  • 中文
  • Deutsch
  • Français
  • Español
  • 日本語
  • Português do Brasil
  • Русский язык
GitHub
  • 实战指南

    • 实战指南
    • 设置
    • 帮助
    • 系统
    • 解析
    • 外部 Shell 脚本
    • 模式匹配
    • 自定义补全器
    • 外部命令补全器
    • 模块的应用
    • 处理文件
    • Git
    • 解析 Git 日志
    • 使用 input listen 对按键进行操作
    • HTTP
    • Direnv
    • ssh-agent
    • 高级表格工作流
    • Polars vs Pandas vs Nushell
    • jq vs Nushell

使用 input listen 对按键进行操作

常见的"按键监听"模式是:

  • 监听特定按键(或一组按键)被按下
  • 根据按下的按键采取行动
  • 如果未按下预期按键,则循环

有几种模式可以实现这一点,每种模式都有优缺点。你可以选择以下最适合你用例和编码风格的其中一种模式:

  1. 第一次尝试可能是以下简单循环。这适用于某些情况,但 loop 本身无法返回值:

    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. 如果你需要返回值,可以在输入循环结束后使用可变变量保存按键结果,然后根据捕获的按键返回一个值:

    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
      }
    }
    
    # 根据可变变量中捕获的按键进行操作
    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. 此版本使用一个自定义命令,该命令递归调用自身,直到按下所需按键之一。但是,请注意,Nushell 根据 $env.config.recursion_limit 的值(默认为 50)限制递归调用的次数。按住 y 键(未监控)以演示基于递归限制的提前退出。

    请注意,此版本不需要 break 语句。

    def run_some_code [] {
      print "I'm running the code and returning 42"
      42
    }
    
    print '(a) Run some code (x) Exit'
    
    def input_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'
      } else if ($key.code == 'c') and ($key.modifiers == ['keymodifiers(control)']) {
          print 'Terminated with Ctrl-C'
      } else {
          print "That key wasn't recognized."
          print 'Press (a) to run some code or (x) to Exit'
          # 递归
          input_loop
      }
    }
    # 启动循环
    try {
      input_loop
    } catch {|e| print ($e.debug)}
  4. generate 命令提供了一个功能性循环替代方案,没有递归限制或可变变量。generate 还可以将多个结果收集到列表中,并且输出是流式的。

    def run_some_code [] {
      print "I'm running the code and returning 42"
      42
    }
    
    print '(a) Run some code (x) Exit'
    
    let key_generator = {|_|
      let key = (input listen --types [key])
    
      if ($key.code == 'a') and ($key.modifiers == []) {
          # 返回没有 "next" 的 "out" 记录会终止循环
          { out: (run_some_code) }
      } else if ($key.code == 'x') and ($key.modifiers == []) {
          print 'User exited'
          { out: null }
      } else if ($key.code == 'c') and ($key.modifiers == ['keymodifiers(control)']) {
          print 'Terminated with Ctrl-C'
          { out: null }
      } else {
          print "That key wasn't recognized."
          print 'Press (a) to run some code or (x) to Exit'
          # 下一个按键生成
          { next: null }
      }
    }
    
    generate null $key_generator | get 0

使用带有键码列表的 match 语句

上述示例使用硬编码键值和 if/else 语句。你可能会发现使用带有键码和修饰符列表的 match 语句更容易维护代码。使用此技术,上面的第二个示例可能看起来像:

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

let keys = {
  # [ key.code key.modifiers ]
  a:      [ 'a' [] ]
  x:      [ 'x' [] ]
  ctrl-c: [ 'c' ['keymodifiers(control)'] ]
}
mut key = {keycode: '', modifiers: ['']}
print '(a) Run some code (x) Exit'

loop {
  $key = (input listen --types [key])
  match [$key.code $key.modifiers] {
    $keymatch if $keymatch == $keys.a => {break}
    $keymatch if $keymatch == $keys.x  => {print 'User exited'; break}
    $keymatch if $keymatch == $keys.ctrl-c => {print 'Terminated with Ctrl-C'; break}
    _ => {
      print "That key wasn't recognized"
      print 'Press (a) to run some code or (x) to Exit'
      continue
    }
  }
}

# 根据可变变量中捕获的按键进行操作
match [$key.code $key.modifiers] {
  $k if $k == $keys.a => {run_some_code}
}
在GitHub上编辑此页面
Contributors: voyage200🍬
Prev
解析 Git 日志
Next
HTTP