1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}
-- | Terminal detection and output mode selection
module Omni.Log.Terminal
( TerminalInfo (..),
OutputMode (..),
detectTerminal,
truncateToWidth,
)
where
import Alpha
import qualified Data.Text as Text
import qualified System.Console.ANSI as ANSI
import qualified System.Environment as Env
data OutputMode
= RichMultiLine -- Wide terminals (≥80 cols)
| SingleLine -- Narrow terminals (40-79 cols)
| SimpleFallback -- Very narrow (<40) or dumb terminals
deriving (Eq, Show)
data TerminalInfo = TerminalInfo
{ tiWidth :: Int,
tiHeight :: Int,
tiMode :: OutputMode,
tiSupportsANSI :: Bool
}
deriving (Eq, Show)
detectTerminal :: IO TerminalInfo
detectTerminal = do
term <- Env.lookupEnv "TERM"
area <- Env.lookupEnv "AREA"
modeOverride <- Env.lookupEnv "BILD_OUTPUT_MODE"
-- Check if we support ANSI
let supportsANSI = case (term, area) of
(Just "dumb", _) -> False
(_, Just "Live") -> False -- production logs
(Nothing, _) -> False
_ -> True
-- Get terminal size
mSize <- ANSI.getTerminalSize
let (width, height) = case mSize of
Just (h, w) -> (w, h)
Nothing -> (80, 24) -- sensible default
-- Determine mode
let autoMode
| not supportsANSI = SimpleFallback
| width < 40 = SimpleFallback
| width < 80 = SingleLine
| otherwise = RichMultiLine
-- Allow manual override
let mode = case modeOverride of
Just "simple" -> SimpleFallback
Just "single" -> SingleLine
Just "rich" -> RichMultiLine
_ -> autoMode
pure
TerminalInfo
{ tiWidth = width,
tiHeight = height,
tiMode = mode,
tiSupportsANSI = supportsANSI
}
-- | Truncate text to fit width with ellipsis
truncateToWidth :: Int -> Text -> Text
truncateToWidth maxWidth text
| Text.length text <= maxWidth = text
| maxWidth <= 3 = Text.take maxWidth text
| otherwise = Text.take (maxWidth - 3) text <> "..."
|