@@ -4,7 +4,7 @@ mod printer;
44
55use anyhow:: Result ;
66use pico_args:: Arguments ;
7- use std:: io:: { IsTerminal , Write } ;
7+ use std:: io:: Write ;
88use std:: path:: PathBuf ;
99
1010/// 顏色輸出模式
@@ -28,16 +28,55 @@ impl ColorMode {
2828 }
2929 }
3030
31- /// 根據模式和 TTY 狀態決定是否啟用顏色
31+ /// 根據模式和輸出目標決定是否啟用顏色
32+ /// auto 模式:終端和管道有顏色,文件重定向無顏色
3233 fn should_colorize ( & self ) -> bool {
3334 match self {
34- ColorMode :: Auto => std :: io :: stdout ( ) . is_terminal ( ) ,
35+ ColorMode :: Auto => ! is_redirected_to_file ( ) ,
3536 ColorMode :: Always => true ,
3637 ColorMode :: Never => false ,
3738 }
3839 }
3940}
4041
42+ /// 檢測 stdout 是否重定向到普通文件
43+ /// 返回 true 表示重定向到文件(應該禁用顏色)
44+ /// 返回 false 表示終端或管道(應該啟用顏色)
45+ fn is_redirected_to_file ( ) -> bool {
46+ use std:: io:: IsTerminal ;
47+
48+ // 如果是終端,肯定不是文件重定向
49+ if std:: io:: stdout ( ) . is_terminal ( ) {
50+ return false ;
51+ }
52+
53+ // 不是終端,需要進一步檢查是管道還是文件
54+ // 在 Unix 系統上,可以用 fstat 檢查
55+ #[ cfg( unix) ]
56+ {
57+ use std:: os:: unix:: io:: AsRawFd ;
58+ let fd = std:: io:: stdout ( ) . as_raw_fd ( ) ;
59+
60+ unsafe {
61+ let mut stat: libc:: stat = std:: mem:: zeroed ( ) ;
62+ if libc:: fstat ( fd, & mut stat) == 0 {
63+ // S_ISREG: 普通文件
64+ // S_ISFIFO: 管道(FIFO)
65+ // S_ISCHR: 字符設備(終端)
66+ return ( stat. st_mode & libc:: S_IFMT ) == libc:: S_IFREG ;
67+ }
68+ }
69+ // Unix 檢查失敗,保守處理
70+ return false ;
71+ }
72+
73+ // Windows:不是 TTY 就禁用顏色(無法區分管道和文件)
74+ #[ cfg( not( unix) ) ]
75+ {
76+ true
77+ }
78+ }
79+
4180struct Args {
4281 files : Vec < PathBuf > ,
4382 encoding : Option < String > ,
0 commit comments