如何干净地分割shell命令输出的stdout和stderr并在Vim状态行中显示后者?

时间:2018-11-14 15:41:58

标签: vim statusbar stderr

我将Vim用作仪表板,并使用各种从宏运行的外部(过滤)命令监视/更新许多表。除了错误输出(尽管我已经解决了80%的消息集成问题,还不完美,它们仍然无法正常工作。有关此类应用的故事,请参见p.s。)。

例如,下表适用于“我爱咖啡”游戏:

TYPE  | STAT |    NAME    | GOAL | DONE | TODO | S1 | S2 | S3
drink | .    | Latte      |  250 |  178 |   72 | .  | .  | .
drink | .    | Cocoa      |   99 |   46 |   50 | .  | 3  | .
drink | .    | Mocha      |  250 |  190 |   40 | 12 | 8  | .
drink | .    | Espresso   |   30 |    0 |   20 | 10 | .  | .
drink | .    | Iced Latte |   54 |    8 |   37 | .  | .  | 9
cake  | .    | Egg Tart   |   25 |   15 |    4 | 6  | .  | .
cake  | .    | Tiramisu   |   36 |    6 |   20 | 4  | 6  | .
cake  | .    | Brûlée     |   11 |    0 |    9 | .  | 2  | .
cake  | v    | Pudding    |   20 |   20 |    0 | .  | .  | .

我在寄存器s中具有以下宏:

'oV}!order-update.pl 2>/tmp/vim.err ^M:if getfsize('/tmp/vim.err')>0|echo join(readfile('/tmp/vim.err'),"\|")|endif ^M'o

({^M是字符ctrl-M), 当我触摸Store1 / 2/3中的数量时,这有助于更新DONETODO列。 (如果完成,将进行v检查,并将行向下移动到历史区域的顶部。)

S1 / S2 / S3的数目有问题时,重定向2>将把stderr输出从stdout输出中溢出并保存在{{ 1}}文件。 (不要弄乱桌子)

vim.err块将返回错误输出,并将其回显到状态行。当我将if...endif放入Store3 drink: 9 > 8 max时,它将打印9。 (但是S3最多可以容纳8杯饮料。)

我的问题是最后一个ex命令行:

S3
如果没有错误,

将保留在状态行中。

我该如何改善?


p.s。

此类应用的故事

上面的(简化的)示例演示了如何将Vim用作快速电子表格,因为我每天都会更新许多表。好处是-我不必离开我最喜欢的Vim。

通过突出显示一些语法,Vim可以用我最喜欢的方式显示这些表。 (取决于这些值)

使用相关过滤器,可以根据值的依赖性正确地更新每个表。

这些年来,我为各种项目开发了许多语法/过滤器对。最近我意识到我还没有将过滤器的错误消息集成到Vim的环境中。这样的消息将被随机合并到正常输出中并组成一个混乱的表。 (使用Vim的默认设置shellredir =“>%s 2> $ 1”)

我的目的是收集过滤器的stderr消息并将其放入Vim的状态行中。

在我的实验中取得了一些结果:

  1. 在宏中指定的“ 2> vim.err”可以否决默认的“ 2>&1”并将stderr拆分为临时文件。

  2. readfile()函数非常适合读取整个文件。

  3. 对于检测到的较小错误,最好不要以非零值退出过滤器。这样的价值将使Vim做更多的事情,并提示“点击进入”。

让stderr消息平稳地适应状态栏是我的最后一个难题。

2 个答案:

答案 0 :(得分:1)

将宏保留在寄存器中对于在单个编辑会话中完成的重复性任务很好。对于您经常需要的事情,我将定义一个适当的 mapping 。使用Vim,“升级”很简单:宏内容成为:map命令的右侧(|变成<Bar>,而^M变成{{1 }}),您将其放入<CR>

~/.vimrc

如果您使用:nnoremap <Leader>s 'oV}!order-update.pl ... ,则不会打印密钥,并且您应该只看到:nnoremap <silent>的结果。


要务实地修复宏,只需在末尾添加:echo

答案 1 :(得分:1)

我认为“ else | echo”不是始终清除状态行的好方法。这很丑陋,并且没有针对您的宏进行优化。

从过滤器程序的stderr中查找tmpfile vim.err的内容。如果过滤器看不到任何奇怪的东西,它应该不包含任何内容。空内容将帮助您在“确定”条件下清除状态行。我会将您的宏重写为(更简单,更简洁):

'oV}!order-update.pl 2>/tmp/vim.err ^M:echo join(readfile('/tmp/vim.err'),"\|") ^M'o

此外,我不同意卡尔卡特先生的评论:“保存在寄存器中的宏仅对单个编辑会话有用”。实际上,宏保存在.viminfo中,并且在会话之间可用。除非您将它们分配为空,否则它们永远不会消失。在我看来,宏与映射一样强大。此外,宏比映射更方便(更易于创建和维护)。至少您可以免去映射的噩梦。只有在足够成熟且对全局有用的情况下,我才会将宏转录为映射。