vint (vim lint) 的解决方法不允许来自标准输入的输入

Workaround for vint (vim lint) not allowing input from stdin

我有一个不接受标准输入的程序,我必须将我的文件作为标准输入传递。 我试图编写一个包装器,但由于某种原因,过程替换不起作用:

#!/bin/bash

vint "$@" <(cat /dev/stdin)

产量:

ERROR: no such file or directory: `/dev/fd/63`

ls -ld /dev/fd 的输出:

> dr-xr-xr-x  1 root  wheel  0 Nov 29 10:57 /dev/fd/

重现步骤:

  1. 创建一个 vim 文件:
cat <<EOF > myvim.vim
set nocompatible
EOF
  1. 安装vint
  2. 创建包装器脚本(如上所述)
  3. 运行这个:
cat myvim.vim | vint-wrapper

我怎样才能实现这个解决方法?

简短的回答:解决问题

vint 不接受任何类型的套接字或 FIFO:它只允许常规文件作为输入。因此,您需要在 运行 之前将标准输入转储到常规文件中:

#!/usr/bin/env bash
tempfile=$(mktemp "${TMPDIR:-/tmp}/vint.XXXXXX") || exit
trap 'rm -f "$tempfile"' EXIT
cat >"$tempfile" || exit
vint "$tempfile"

...或者,如果您愿意依赖未记录的实施细节,请使用 heredoc 或 herestring 使 shell 代表您进行临时文件管理,同时使用 - 作为输入文件名(vint 明确豁免):

#!/usr/bin/env bash
vint - <<<"$(cat)"

较长的答案:为什么会这样

发生错误是因为 vint 明确检查给定的文件名 是否是一个文件 ,并拒绝其他任何内容:

if not self._should_read_from_stdin(env):
    for path_to_lint in paths_to_lint:
        if not path_to_lint.exists() or not path_to_lint.is_file():
            logging.error('no such file or directory: `{path}`'.format(
                path=str(path_to_lint)))
            parser.exit(status=1)

...但是,看到 _should_read_from_stdin 了吗?这很重要; vint 可以 从 stdin 读取,但必须给出 - 作为要使用的文件名。

cat myvim.vim | vint -

然而,即便如此,vint 要求给定的文件是可搜索的,而 FIFO 和管道则不是。因此,这将导致:

io.UnsupportedOperation: underlying stream is not seekable

...因为vint检查文件是否有BOM表示是否有多字节字符的方式涉及读取开头然后倒带;管道不能倒带,但只能从前到后读取一次。