From e4e120bb8ec955954fd4fab4181b842deb4a9968 Mon Sep 17 00:00:00 2001 From: Joachim Breitner Date: Fri, 7 Oct 2016 11:41:02 -0400 Subject: [PATCH] Add XMonad.Prompt.Unicode I have been using this code locally for years now, and it turned out to be quite useful in many cases, so I thought it is about time to submit it to the repository. --- CHANGES.md | 5 ++ XMonad/Prompt/Unicode.hs | 103 +++++++++++++++++++++++++++++++++++++++ xmonad-contrib.cabal | 5 +- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 XMonad/Prompt/Unicode.hs diff --git a/CHANGES.md b/CHANGES.md index cef3fe6a..b820f60e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -20,6 +20,11 @@ the order of windows in the final layout. Any unmatched windows go to the end of the order. + * `XMonad.Prompt.Unicode` + + A prompt to search a unicode character by its name, and put it into the + clipboard. + * `XMonad.Util.Ungrab` Release xmonad's keyboard and pointer grabs immediately, so diff --git a/XMonad/Prompt/Unicode.hs b/XMonad/Prompt/Unicode.hs new file mode 100644 index 00000000..11ec58cd --- /dev/null +++ b/XMonad/Prompt/Unicode.hs @@ -0,0 +1,103 @@ +{- | +Module : XMonad.Prompt.Unicode +Copyright : (c) 2016 Joachim Breitner +License : BSD-style (see LICENSE) + +Maintainer : +Stability : stable + +A prompt for searching unicode characters by name and inserting them into +the clipboard. + +Requires the file @\/usr\/share\/unicode\/UnicodeData.txt@ (shipped in the package +@unicode-data@ on Debian) and the @xsel@ tool. +-} + +module XMonad.Prompt.Unicode ( + -- * Usage + -- $usage + unicodePrompt + ) where + +import qualified Data.ByteString.Char8 as BS +import Data.Attoparsec.ByteString.Char8 hiding (take) +import Data.Char +import Control.Applicative +import System.Environment +import System.IO +import System.IO.Unsafe +import System.IO.Error +import Control.Arrow +import Data.List +import Text.Printf + +import XMonad +import XMonad.Util.Run +import XMonad.Prompt hiding (endOfLine) + +{- $usage + +You can use this module by importing it, along with +"XMonad.Prompt", into your ~\/.xmonad\/xmonad.hs file: + +> import XMonad.Prompt +> import XMonad.Prompt.Unicode + +and adding an appropriate keybinding, for example: + +> , ((modm .|. controlMask, xK_u), unicodePrompt def) + +-} + +unicodeDataFilename :: String +unicodeDataFilename = "/usr/share/unicode/UnicodeData.txt" + +entries :: [(Char, BS.ByteString)] +entries = unsafePerformIO $ do + datE <- tryIOError $ BS.readFile unicodeDataFilename + case datE of + Left e -> do + hPutStrLn stderr $ "Could not read file \"" ++ unicodeDataFilename ++ "\"" + hPutStrLn stderr $ show e + hPutStrLn stderr $ "Do you have unicode-data installed?" + return [] + Right dat -> case parseOnly (p <* endOfInput) dat of + Left e -> do + hPutStrLn stderr $ "Failed to parse UnicodeData: " ++ show e + return [] + Right r -> return $ sortOn (BS.length.snd) r +{-# NOINLINE entries #-} + +p = many' $ do + c <- chr <$> hexadecimal + char ';' + d <- takeTill (== ';') + char ';' + skipWhile (/= '\n') + endOfLine + return (c,d) + +searchUnicode :: String -> [(Char, String)] +searchUnicode s = map (second BS.unpack) $ filter go entries + where w = map BS.pack $ filter (all isAscii) $ filter ((> 1) . length) $ words $ map toUpper s + go (c,d) = all (`BS.isInfixOf` d) w + +-- | Prompt the user for a unicode character to be inserted into the paste buffer of the X server. +unicodePrompt :: XPConfig -> X () +unicodePrompt config = mkXPrompt Unicode config unicodeCompl paste + where + unicodeCompl [] = return [] + unicodeCompl s = do + return $ map (\(c,d) -> printf "%s %s" [c] d) $ take 20 $ searchUnicode s + + paste [] = return () + paste (c:_) = do + runProcessWithInput "xsel" ["-i"] [c] + return () + +data Unicode = Unicode +instance XPrompt Unicode where + showXPrompt Unicode = "Unicode: " + commandToComplete Unicode s = s + nextCompletion Unicode = getNextCompletion + diff --git a/xmonad-contrib.cabal b/xmonad-contrib.cabal index 6b60b150..64ed585c 100644 --- a/xmonad-contrib.cabal +++ b/xmonad-contrib.cabal @@ -54,7 +54,9 @@ flag testing default: False library - build-depends: base >= 4.5 && < 5, + build-depends: attoparsec >= 0.13 && < 0.14, + base >= 4.5 && < 5, + bytestring >= 0.10 && < 0.11, containers >= 0.5 && < 0.6, directory, extensible-exceptions, @@ -298,6 +300,7 @@ library XMonad.Prompt.Shell XMonad.Prompt.Ssh XMonad.Prompt.Theme + XMonad.Prompt.Unicode XMonad.Prompt.Window XMonad.Prompt.Workspace XMonad.Prompt.XMonad