bat
bat copied to clipboard
Idea: determine filename of stdin for shell redirection to detect filetype
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#.}
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?
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.