bat icon indicating copy to clipboard operation
bat copied to clipboard

Idea: determine filename of stdin for shell redirection to detect filetype

Open LunarLambda opened this issue 2 years ago • 2 comments

When using bat as a filter/pager (or in my case, as zsh's READNULLCMD, where < test.txt is equivalent to bat < test.txt), it should be possible to determine the filename pointed to by stdin through mechanisms similar to how Rust implements std::fs::canonicalize.

This should allow detecting if stdin was redirected from a file, and allow detecting the language based on the file's extension:

On Linux, std::fs::canonicalize("/proc/self/fd/0") should suffice, for Windows one can use the following:

#include <windows.h>
#include <stdio.h>

int main() {
        HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
        char buf[MAX_PATH] = {0};
        GetFinalPathNameByHandleA(h, buf, MAX_PATH, 0);
        printf("stdin is: %s\n", buf);
}

./test < test.txt prints stdin is \\?\C:\Users\LunarLambda\test.txt

Unsure what a generic-unix solution would look like, BSD has fcntl(F_GETPATH, ...) and realpath.

For the shell case, this works as a wrapper script:

#!/bin/sh
ext=$(python3 -c 'import os.path; import sys; print(os.path.splitext(sys.argv[1])[1])' "$(realpath /proc/self/fd/0)")
exec bat -n ${ext:+-l} ${ext#.}

LunarLambda avatar Aug 31 '23 08:08 LunarLambda

Interesting — thank you!

I had a similar idea once for inputs from other processes through a pipe, but that turned out not to work very reliably because often those processes have already finished when attempting to find them (https://unix.stackexchange.com/questions/405485/name-of-the-process-on-the-other-end-of-a-unix-pipe).

Do you know if other tools use a similar mechanism? What kind of potential problems do you see with this approach?

sharkdp avatar Sep 01 '23 18:09 sharkdp

I'm not aware of any tools that do this, it is a very niche case and as shown, can be implemented with a basic wrapper script

Downsides are that it requires OS-specific code that isn't served by std and there's no single cfg(unix) approach. It should however work consistently on platforms where it is supported, and doesn't rely on any features that would affect MSRV or anything.

LunarLambda avatar Sep 01 '23 19:09 LunarLambda