हास्केल में टर्मिनल की चौड़ाई कैसे प्राप्त करें?टर्मिनल चौड़ाई प्राप्त करें Haskell
चीजें मैं
System.Posix.IOCtl (could not figure out how to get it to work)
यह केवल यूनिक्स काम करने के लिए है की कोशिश की।
धन्यवाद
हास्केल में टर्मिनल की चौड़ाई कैसे प्राप्त करें?टर्मिनल चौड़ाई प्राप्त करें Haskell
चीजें मैं
System.Posix.IOCtl (could not figure out how to get it to work)
यह केवल यूनिक्स काम करने के लिए है की कोशिश की।
धन्यवाद
आप ncurses पर निर्भरता नहीं करना चाहते हैं, यहाँ उचित ioctl()
FFI का उपयोग कर अनुरोध का एक आवरण, Getting terminal width in C?
TermSize.hsc
{-# LANGUAGE ForeignFunctionInterface #-}
module TermSize (getTermSize) where
import Foreign
import Foreign.C.Error
import Foreign.C.Types
#include <sys/ioctl.h>
#include <unistd.h>
-- Trick for calculating alignment of a type, taken from
-- http://www.haskell.org/haskellwiki/FFICookBook#Working_with_structs
#let alignment t = "%lu", (unsigned long)offsetof(struct {char x__; t (y__); }, y__)
-- The ws_xpixel and ws_ypixel fields are unused, so I've omitted them here.
data WinSize = WinSize { wsRow, wsCol :: CUShort }
instance Storable WinSize where
sizeOf _ = (#size struct winsize)
alignment _ = (#alignment struct winsize)
peek ptr = do
row <- (#peek struct winsize, ws_row) ptr
col <- (#peek struct winsize, ws_col) ptr
return $ WinSize row col
poke ptr (WinSize row col) = do
(#poke struct winsize, ws_row) ptr row
(#poke struct winsize, ws_col) ptr col
foreign import ccall "sys/ioctl.h ioctl"
ioctl :: CInt -> CInt -> Ptr WinSize -> IO CInt
-- | Return current number of (rows, columns) of the terminal.
getTermSize :: IO (Int, Int)
getTermSize =
with (WinSize 0 0) $ \ws -> do
throwErrnoIfMinus1 "ioctl" $
ioctl (#const STDOUT_FILENO) (#const TIOCGWINSZ) ws
WinSize row col <- peek ws
return (fromIntegral row, fromIntegral col)
के स्वीकार किए जाते हैं उत्तर के आधार पर है यह hsc2hs
preprocessor का उपयोग करता है ताकि सी हार्डर्सिंग के बजाय सी हेडर पर आधारित सही स्थिरांक और ऑफसेट का पता लगाया जा सके। मुझे लगता है कि यह या तो जीएचसी या हास्केल प्लेटफ़ॉर्म के साथ पैक किया गया है, इसलिए संभावना है कि आपके पास पहले से ही होगा।
यदि आप कैबल का उपयोग कर रहे हैं, तो आप TermSize.hs
को अपने .cabal
फ़ाइल में जोड़ सकते हैं और यह स्वचालित रूप से TermSize.hsc
से इसे उत्पन्न करने के तरीके के बारे में जानेंगे। अन्यथा, आप hsc2hs TermSize.hsc
को .hs
फ़ाइल जेनरेट करने के लिए मैन्युअल रूप से चला सकते हैं जिसे आप जीएचसी के साथ संकलित कर सकते हैं।
आप hcurses इस्तेमाल कर सकते हैं। एक बार पुस्तकालय आरंभ करने के बाद, आप स्क्रीन पर पंक्तियों और स्तंभों की संख्या प्राप्त करने के लिए scrSize
का उपयोग कर सकते हैं।
System.Posix.IOCtl
का उपयोग करने के लिए आपको TIOCGWINSZ
अनुरोध है, जो निम्नलिखित संरचना में भर जाता है प्रतिनिधित्व करने के लिए एक डेटा प्रकार को परिभाषित करने के लिए है:
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel; /* unused */
unsigned short ws_ypixel; /* unused */
};
आप इस जानकारी धारण करने के लिए एक हास्केल डेटा के प्रकार को परिभाषित करने की आवश्यकता होगी,
:{-# LANGUAGE RecordWildCards #-}
import Foreign.Storable
import Foreign.Ptr
import Foreign.C
data Winsize = Winsize { ws_row :: CUShort
, ws_col :: CUShort
, ws_xpixel :: CUShort
, ws_ypixel :: CUShort
}
instance Storable Winsize where
sizeOf _ = 8
alignment _ = 2
peek p = do { ws_row <- peekByteOff p 0
; ws_col <- peekByteOff p 2
; ws_xpixel <- peekByteOff p 4
; ws_ypixel <- peekByteOff p 6
; return $ Winsize {..}
}
poke p Winsize {..} = do { pokeByteOff p 0 ws_row
; pokeByteOff p 2 ws_col
; pokeByteOff p 4 ws_xpixel
; pokeByteOff p 6 ws_ypixel
}
आप अपने अनुरोध का प्रतिनिधित्व करने के एक डमी डेटा प्रकार बनाने की जरूरत अब,: और यह Storable
का एक उदाहरण बनाने के
data TIOCGWINSZ = TIOCGWINSZ
अंत में, आपको अपना अनुरोध IOControl
का उदाहरण बनाने की आवश्यकता है, और इसे Winsize
डेटा प्रकार से संबद्ध करें।
instance IOControl TIOCGWINSZ Winsize where
ioctlReq _ = ??
आप निरंतर (अपने सिस्टम पर 0x5413
) अपने हेडर फाइल में TIOCGWINSZ
द्वारा प्रतिनिधित्व के साथ ??
को बदलने के लिए की आवश्यकता होगी।
अब, आप ioctl
जारी करने के लिए तैयार हैं। यह आदेश इनपुट डेटा के बारे में परवाह नहीं करता है, तो आप ioctl'
फार्म का उपयोग करना चाहते हैं:
main = do { ws <- ioctl' 1 TIOCGWINSZ
; putStrLn $ "My terminal is " ++ show (ws_col ws) ++ " columns wide"
}
ध्यान दें कि 1 STDOUT को दर्शाता है।
पुhew!
क्या यह थोड़ा अधिक नहीं है? क्या कुछ आसान नहीं है? –
नोट: 'ioctl' कॉल में '0' एसटीडीआईएन को संदर्भित करता है, इसलिए अगर एसटीडीआईएन रीडायरेक्ट किया जाता है तो यह विफल हो जाता है। टर्मिनल चौड़ाई प्राप्त करने के लक्ष्य को मानना प्रारूप को प्रारूपित करना है, इसके बजाय STDOUT से पूछना बेहतर हो सकता है। – hammar
अच्छा बिंदु। मैंने अपना जवाब अपडेट कर लिया है, लेकिन आपका जवाब कहीं अधिक मजबूत है। काश मैं आपको 1 से अधिक वोट दे सकता हूं; उपयोगी जानकारी से भरा हुआ अगर आपका जवाब! – pat
जब से तुम केवल यूनिक्स पर इस की जरूरत है, मैं सलाह देते हैं:
resizeOutput <- readProcess "/usr/X11/bin/resize" [] ""
और फिर उत्पादन को पार्स का एक छोटा-बिट कर रही। यह 100% पोर्टेबल नहीं हो सकता है, लेकिन मुझे विश्वास है कि आप तर्क के साथ resize
प्रदान कर सकते हैं (विशेष रूप से -u
देखें), इसलिए आपको काफी लगातार आउटपुट मिलेगा।
यह अच्छा है, मुझे hsc2hs को देखने की ज़रूरत है! – pat
बहुत अच्छा, धन्यवाद –