summaryrefslogtreecommitdiff
path: root/Omni/Log/Terminal.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Omni/Log/Terminal.hs')
-rw-r--r--Omni/Log/Terminal.hs78
1 files changed, 78 insertions, 0 deletions
diff --git a/Omni/Log/Terminal.hs b/Omni/Log/Terminal.hs
new file mode 100644
index 0000000..1230eb3
--- /dev/null
+++ b/Omni/Log/Terminal.hs
@@ -0,0 +1,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 <> "..."