packages feed

fontwhich 0.1.0 → 0.2

raw patch · 4 files changed

+104/−43 lines, 4 filesdep +unicode-data-namesdep +unicode-data-scripts

Dependencies added: unicode-data-names, unicode-data-scripts

Files

ChangeLog.md view
@@ -1,4 +1,10 @@ # fontwhich releases +## 0.2 (2026-03-12)+- add --unicode for unicode data output (uses `unicode-data`)+- rename --hex to --utf8 (for hex bytes)+- show number of pango items with --utf8 or --unicode+- only print number of bytes with --utf8 or --unicode+ ## 0.1.0 (2026-02-27) - initial release with --font --lang and --hex
README.md view
@@ -8,12 +8,19 @@  ## Usage +`$ fontwhich --version`++```+0.2+```+ `$ fontwhich --help`  ``` fontwhich -Usage: fontwhich [--version] [-f|--font FONT] [-l|--lang LANG] [-x|--hex] [TEXT]+Usage: fontwhich [--version] [-f|--font FONT] [-l|--lang LANG] [-b|--utf8] +                 [-u|--unicode] [TEXT]    Describes the fonts used to render text with pango @@ -22,13 +29,13 @@   --version                Show version   -f,--font FONT           Base font [default: Sans]   -l,--lang LANG           Language code-  -x,--hex                 Output UTF-8 hex codes+  -b,--utf8                Output UTF-8 hex codes+  -u,--unicode             Output Unicode data ```  `$ fontwhich Hello 🌍 World 世界`  ```-23 bytes 'Hello ' : Noto Sans '🌍' : Noto Color Emoji ' World ' : Noto Sans@@ -38,7 +45,6 @@ `$ fontwhich -f Serif "こんにちは 😀 世界"`  ```-27 bytes 'こんにちは ' : Noto Serif CJK JP '😀' : Noto Color Emoji ' ' : Noto Serif CJK JP@@ -51,13 +57,36 @@ Primary font for ja is: "Noto Sans CJK JP" ``` -`$ fontwhich --hex 🍊`+`$ fontwhich --utf8 🌳`  ```-4 bytes+4 bytes;+'🌳' [f0 9f 8c b3] : Noto Color Emoji+```++`$ fontwhich --unicode αβ१२`++```+10 bytes; 2 pango items+'αβ' : Noto Sans+α <U+03B1>: GREEK SMALL LETTER ALPHA [Greek]+β <U+03B2>: GREEK SMALL LETTER BETA [Greek]+'१२' : Noto Sans Devanagari+१ <U+0967>: DEVANAGARI DIGIT ONE [Devanagari]+२ <U+0968>: DEVANAGARI DIGIT TWO [Devanagari]+```++One can use both options together:++`$ fontwhich --utf8 🍊 --unicode`++```+4 bytes; '🍊' [f0 9f 8d 8a] : Noto Color Emoji+🍊 <U+1F34A>: TANGERINE [Common] ``` + ## Building and installation On Fedora: ```@@ -68,7 +97,7 @@ There is a copr repo: <https://copr.fedorainfracloud.org/coprs/petersen/fontwhich/>  ## Misc-Code was assisted with Gemini Pro 3.1.+Code assisted with Gemini 3.1.  The tool is related conceptually to <https://github.com/sudipshil9862/whichfont> (C codebase). 
fontwhich.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                fontwhich-version:             0.1.0+version:             0.2 synopsis:            Determine fonts used to render text description:         Fontwhich is a commandline tool that used pango to determine which@@ -17,13 +17,10 @@ build-type:          Simple extra-doc-files:     README.md                      ChangeLog.md--- tested-with:         GHC == 8.10.7---                       || == 9.0.2---                       || == 9.2.8---                       || == 9.4.8---                       || == 9.6.7---                       || == 9.8.4---                       || == 9.10.3+tested-with:         GHC == 9.6.7+                      || == 9.8.4+                      || == 9.10.3+                      || == 9.12.3  source-repository head   type:                git@@ -41,7 +38,9 @@                        gi-pangocairo,                        simple-cmd,                        simple-cmd-args,-                       text+                       text,+                       unicode-data-names,+                       unicode-data-scripts   default-language:    Haskell2010   ghc-options:         -Wall   if impl(ghc >= 8.0)
src/Main.hs view
@@ -1,17 +1,19 @@ -- SPDX-License-Identifier: BSD-3-Clause -import Control.Monad.Extra (whenJust)+import Control.Monad.Extra (forM_, when, whenJust) import qualified Data.ByteString as B+import Data.Char (ord) import Data.Maybe (fromMaybe) import qualified Data.Text as T import qualified Data.Text.Encoding as TE+import qualified GI.Pango as Pango+import qualified GI.PangoCairo.Interfaces.FontMap as PangoCairo import SimpleCmd (error', (+-+))-import SimpleCmdArgs+import SimpleCmdArgs hiding (str) import System.Environment (getArgs, withArgs) import Text.Printf (printf)--import qualified GI.Pango as Pango-import qualified GI.PangoCairo.Interfaces.FontMap as PangoCairo+import qualified Unicode.Char.General.Names as UN+import qualified Unicode.Char.General.Scripts as US  import Paths_fontwhich (version) @@ -29,11 +31,12 @@     run     <$> optional (strOptionWith 'f' "font" "FONT" "Base font [default: Sans]")     <*> optional (strOptionWith 'l' "lang" "LANG" "Language code")-    <*> switchWith 'x' "hex" "Output UTF-8 hex codes"+    <*> switchWith 'b' "utf8" "Output UTF-8 hex codes"+    <*> switchWith 'u' "unicode" "Output Unicode data"     <*> many (strArg "TEXT") -run :: Maybe String -> Maybe String -> Bool -> [String] -> IO ()-run mfont mlang hex txt = do+run :: Maybe String -> Maybe String -> Bool -> Bool -> [String] -> IO ()+run mfont mlang hex unicode txt = do   -- Get a default Font Map and Context   fontMap <- PangoCairo.fontMapGetDefault   context <- Pango.fontMapCreateContext fontMap@@ -66,33 +69,57 @@       Pango.contextSetLanguage context mplang        let utf8Bytes = TE.encodeUtf8 myText-      putStrLn $ show (B.length utf8Bytes) +-+ "bytes"+      when (hex || unicode) $+        putStr $ show (B.length utf8Bytes) +-+ "bytes;"        -- start_index, length, cached_iter       items <- Pango.itemize context myText 0 (fromIntegral $ B.length utf8Bytes) attr Nothing-      mapM_ (printItemInfo hex utf8Bytes) items+      when (hex || unicode) $+        putStrLn $+        if length items > 1+        then ' ' : show (length items) +-+ "pango items"+        else ""+      mapM (itemString utf8Bytes) items >>=+        mapM_ (printItemInfo hex unicode)+  where+    itemString :: B.ByteString -> Pango.Item -> IO (String, Pango.Item)+    itemString utf8Bytes item = do+      -- Offsets in Pango are bytes+      offset <- Pango.getItemOffset item+      len <- Pango.getItemLength item+      let itemBytes = B.take (fromIntegral len) $ B.drop (fromIntegral offset) utf8Bytes+      return (T.unpack $ TE.decodeUtf8 itemBytes, item) -printItemInfo :: Bool -> B.ByteString -> Pango.Item -> IO ()-printItemInfo hex utf8Bytes item = do+printItemInfo :: Bool -> Bool -> (String, Pango.Item) -> IO ()+printItemInfo hex unicode (str,item) = do   -- Get the Analysis struct from the Item   analysis <- Pango.getItemAnalysis item    -- Extract the Font used for this specific item   maybeFont <- Pango.getAnalysisFont analysis -  case maybeFont of-    Nothing -> putStrLn "No font assigned to this segment."-    Just font -> do-      desc <- Pango.fontDescribe font-      family <- Pango.fontDescriptionGetFamily desc+  mfamily <-+    case maybeFont of+      Nothing -> do+        putStrLn "No font assigned"+        return Nothing+      Just font ->+        Pango.fontDescribe font >>= Pango.fontDescriptionGetFamily -      -- Offsets in Pango are byte offsets-      offset <- Pango.getItemOffset item-      len <- Pango.getItemLength item-      let itemBytes = B.take (fromIntegral len) $ B.drop (fromIntegral offset) utf8Bytes-          itemText  = TE.decodeUtf8 itemBytes-          hexStr = if hex-                 then "[" ++ unwords [printf "%02x" b | b <- B.unpack itemBytes] ++ "]"-                 else ""-      putStrLn $-        '\'' : T.unpack itemText ++ "'" +-+ hexStr +-+ ":" +-+ maybe "Unknown" T.unpack family+  let hexStr = if hex+             then unwords $ map hexify str+             else ""+  putStrLn $+    '\'' : str ++ "'" +-+ hexStr +-+ ":" +-+ maybe "Unknown" T.unpack mfamily+  when unicode $+    forM_ str $ \char -> do+    putChar char+    let mname = UN.name char+        script = US.script char+        codepoint = printf "U+%04X" (ord char)+    putStrLn $ " <" ++ codepoint ++ ">:" +-+ fromMaybe "unknown codepoint" mname +-+ '[' : show script ++ "]" -- +-+ '(' : US.scriptShortName script ++ ")"+  where+    hexify :: Char -> String+    hexify char =+      let bytes = TE.encodeUtf8 $ T.singleton char+      in '[' : unwords [printf "%02x" b | b <- B.unpack bytes] ++ "]"