You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用{cli}包实现列表自动缩进得到正确格式输出?

问题原因

cli 内部通过状态栈维护输出元素的嵌套层级:调用 cli_ul() 开启无序列表时,会向栈中压入新的列表层级,后续输出默认继承当前层级的缩进;如果列表编写完成后没有显式关闭,后续新调用的 cli_ul() 会被识别为当前列表下的嵌套子列表,连带后续所有输出都叠加额外缩进,就会出现格式异常。

修复方法

以下两种写法都可以实现预期的无嵌套缩进输出:

方法1:显式关闭已完成的列表

每写完一组列表项后,调用 cli_end() 关闭当前打开的列表,弹出对应层级,重置缩进状态:

library(cli)

f <- function() {
  cli::cli_div(theme = list(ul = list(`margin-left` = 2, before = "")))
  
  cli::cli_text("this is my first list:")
  cli::cli_ul()
  for (i in c("a", "b", "c")) {
    cli::cli_li("{.file {i}}")
  }
  cli::cli_end() # 关闭第一个无序列表,重置缩进层级
  
  cli::cli_text("this is my second list:")
  cli::cli_ul()
  for (i in c("d", "e", "f")) {
    cli::cli_li("{.file {i}}")
  }
  cli::cli_end() # 关闭第二个无序列表
  
  cli::cli_alert_info("this is an info")
}

f()

运行后输出完全符合预期:

#> this is my first list:
#>   • 'a'
#>   • 'b'
#>   • 'c'
#> this is my second list:
#>   • 'd'
#>   • 'e'
#>   • 'f'
#> ℹ this is an info

方法2:直接向cli_ul()传入列表项

不需要单独循环调用 cli_li() 添加元素,直接把所有列表项组成字符向量传给 cli_ul(),函数会自动完成列表的开启和闭合,无需手动调用 cli_end():

library(cli)

f <- function() {
  cli::cli_div(theme = list(ul = list(`margin-left` = 2, before = "")))
  
  cli::cli_text("this is my first list:")
  # 直接传入全部列表项,自动处理列表开合
  cli::cli_ul(c("{.file a}", "{.file b}", "{.file c}"))
  
  cli::cli_text("this is my second list:")
  cli::cli_ul(c("{.file d}", "{.file e}", "{.file f}"))
  
  cli::cli_alert_info("this is an info")
}

f()

如果列表项是动态生成的,可以先通过循环或向量处理函数批量生成带格式的字符向量,再传入cli_ul()即可,效果和逐行添加cli_li()完全一致。


内容的提问来源于stack exchange,提问作者bretauv

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:54:21