Terminalin genişliği Haskell'de nasıl bulunur?Terminal genişliğini alın Haskell
şeyler ben bu sadece unix çalışmak zorundadır
System.Posix.IOCtl (could not figure out how to get it to work)
çalıştı.
Teşekkür
Terminalin genişliği Haskell'de nasıl bulunur?Terminal genişliğini alın Haskell
şeyler ben bu sadece unix çalışmak zorundadır
System.Posix.IOCtl (could not figure out how to get it to work)
çalıştı.
Teşekkür
, burada 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)
kabul Yanıta göre FFI kullanarak uygun ioctl()
isteğin bir sarıcı, var Bu, sabit kodlama yapmak yerine C başlıklarına göre doğru sabitleri ve ofsetleri bulmak için hsc2hs
preprocessor kullanır. Sanırım GHC ya da Haskell Platformu ile paketlenmiş, bu yüzden şimdiden şansınız olacak. Eğer Cabal kullanıyorsanız
.cabal
dosyaya
TermSize.hs
ekleyebilir ve otomatik olarak
TermSize.hsc
onu üretmek için nasıl bileceksiniz. Aksi halde, daha sonra GHC ile derleyebildiğiniz bir
.hs
dosyası oluşturmak için
hsc2hs TermSize.hsc
dosyasını çalıştırabilirsiniz.Yalnızca Unix bu gerektiğinden
Sen hcurses kullanabilirsiniz. Kitaplığı başlattıktan sonra, ekranda satır ve sütun sayısını almak için scrSize
'u kullanabilirsiniz. ,
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel; /* unused */
unsigned short ws_ypixel; /* unused */
};
Bu verileri saklayacak bir Haskell veri türünü tanımlamak gerekir: System.Posix.IOCtl
kullanmak için
, aşağıdaki yapıda doldurur TIOCGWINSZ
isteği temsil edecek bir veri türü tanımlamak zorunda
{-# 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
}
: ve ona Storable
bir örneğini yapmak
data TIOCGWINSZ = TIOCGWINSZ
Son olarak, isteğinizi bir IOControl
örneğini oluşturmanız ve Winsize
veri türüyle ilişkilendirmeniz gerekir.
instance IOControl TIOCGWINSZ Winsize where
ioctlReq _ = ??
Sen (sistemimde 0x5413
) sizin başlık dosyalarında TIOCGWINSZ
ile temsil sabiti ile ??
değiştirmeniz gerekir.
Şimdi, ioctl
numarasını vermeye hazırsınız. Bu komut veri girişi umursamıyor, yani ioctl'
formunu kullanmak istiyorum: 1 STDOUT başvurduğu
main = do { ws <- ioctl' 1 TIOCGWINSZ
; putStrLn $ "My terminal is " ++ show (ws_col ws) ++ " columns wide"
}
Not.
Phew! Eğer ncurses'da bir bağımlılık istemiyorsanız
Bu biraz aşırı değil mi? Daha basit bir şey yok mu? –
Not: 'ioctl'' çağrısındaki' '' STDIN’i ifade eder, bu nedenle STDIN yeniden yönlendirilirse bu başarısız olur. Terminal genişliğini elde etmek için hedefin çıktıyı biçimlendirmek olduğunu varsayarak, bunun yerine STDOUT'u sorgulamak daha iyi olabilir. – hammar
İyi nokta. Cevabımı güncelledim, ama cevabınız çok daha sağlam. Keşke size 1 oydan fazlasını verebilseydim; Cevabınız yararlı bilgilerle dolu olduğunda – pat
, ben tavsiye ederim:
resizeOutput <- readProcess "/usr/X11/bin/resize" [] ""
Sonra çıktı ayrıştırma biraz bit yapıyor. Bu,% 100 taşınabilir olmayabilir, ancak ben resize
argümanları ile sağlayabileceğine inanıyorum (özellikle -u
'a bakın), böylece oldukça tutarlı bir çıktı elde edersiniz.
Bu harika, hsc2hs'e bakmam lazım! – pat
Çok güzel, Teşekkürler –