Skip to content

Commit a32d3e3

Browse files
committed
feat: colorized search output
1 parent 0be38ee commit a32d3e3

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

hoogle.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ library
4444
build-depends:
4545
QuickCheck,
4646
aeson,
47+
ansi-terminal,
4748
base > 4 && < 5,
4849
blaze-html,
4950
blaze-markup,

src/Action/Search.hs

+34-13
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import Output.Names
3030
import Output.Tags
3131
import Output.Types
3232
import Query
33+
import System.Console.ANSI
3334

3435
-- -- generate all
3536
-- @tagsoup -- generate tagsoup
@@ -40,19 +41,21 @@ actionSearch :: CmdLine -> IO ()
4041
actionSearch Search{..} = replicateM_ repeat_ $ -- deliberately reopen the database each time
4142
withSearch database $ \store ->
4243
if null compare_ then do
43-
count' <- pure $ fromMaybe 10 count
44-
(q, res) <- pure $ search store $ parseQuery $ unwords query
45-
whenLoud $ putStrLn $ "Query: " ++ unescapeHTML (LBS.unpack $ renderMarkup $ renderQuery q)
46-
let (shown, hidden) = splitAt count' $ nubOrd $ map (targetResultDisplay link) res
44+
-- should we check for color support?
45+
-- --color implies ANSI support, i.e. --color=always
46+
let color' = fromMaybe False color
47+
let count' = fromMaybe 10 count
48+
let (qs, res) = search store $ parseQuery $ unwords query
49+
let (shown, hidden) = splitAt count' $ nubOrd $ map (targetResultDisplay link color' qs) res
50+
whenLoud $ putStrLn $ "Query: " ++ unescapeHTML (LBS.unpack $ renderMarkup $ renderQuery qs)
4751
if null res then
4852
putStrLn "No results found"
4953
else if info then do
50-
putStr $ targetInfo $ head res
54+
putStr $ targetInfo color' qs $ head res
5155
else do
52-
let toShow = if numbers && not info then addCounter shown else shown
5356
if | json -> LBS.putStrLn $ JSON.encode $ maybe id take count $ map unHTMLtargetItem res
5457
| jsonl -> mapM_ (LBS.putStrLn . JSON.encode) $ maybe id take count $ map unHTMLtargetItem res
55-
| otherwise -> putStr $ unlines toShow
58+
| otherwise -> putStr $ unlines $ if numbers then addCounter shown else shown
5659
when (hidden /= [] && not json) $ do
5760
whenNormal $ putStrLn $ "-- plus more results not shown, pass --count=" ++ show (count'+10) ++ " to see more"
5861
else do
@@ -62,21 +65,39 @@ actionSearch Search{..} = replicateM_ repeat_ $ -- deliberately reopen the datab
6265
putStr $ unlines $ searchFingerprintsDebug store (parseType $ unwords query) (map parseType compare_)
6366

6467
-- | Returns the details printed out when hoogle --info is called
65-
targetInfo :: Target -> String
66-
targetInfo Target{..} =
67-
unlines $ [ unHTML targetItem ] ++
68+
targetInfo :: Bool -> [Query] -> Target -> String
69+
targetInfo color qs Target{..} =
70+
unlines $ [ unHTML . (if color then highlightItem qs else id) $ targetItem ] ++
6871
[ unwords packageModule | not $ null packageModule] ++
6972
[ unHTML targetDocs ]
7073
where packageModule = map fst $ catMaybes [targetPackage, targetModule]
7174

7275
-- | Returns the Target formatted as an item to display in the results
7376
-- | Bool argument decides whether links are shown
74-
targetResultDisplay :: Bool -> Target -> String
75-
targetResultDisplay link Target{..} = unHTML $ unwords $
77+
targetResultDisplay :: Bool -> Bool -> [Query] -> Target -> String
78+
targetResultDisplay link color qs Target{..} = unHTML $ unwords $
7679
map fst (maybeToList targetModule) ++
77-
[targetItem] ++
80+
[if color then highlightItem qs targetItem else targetItem] ++
7881
["-- " ++ targetURL | link]
7982

83+
highlightItem:: [Query] -> String -> String
84+
highlightItem qs x
85+
| Just (pre,x) <- stripInfix "<s0>" x, Just (name,post) <- stripInfix "</s0>" x
86+
= pre ++ dull ++ highlight (unescapeHTML name) ++ rst ++ post
87+
| otherwise = x
88+
where
89+
dull = setSGRCode [SetColor Foreground Dull Yellow]
90+
bold = setSGRCode [SetColor Foreground Vivid Yellow]
91+
rst = setSGRCode []
92+
highlight = mconcatMap (\xs@((b,_):_) -> let s = map snd xs in if b then bold ++ s ++ dull else s) .
93+
groupOn fst . (\x -> zip (mapIsInQueries x) x)
94+
where
95+
mapIsInQueries :: String -> [Bool]
96+
mapIsInQueries (x:xs) | m > 0 = replicate m True ++ (mapIsInQueries $ drop (m - 1) xs)
97+
where m = maximum $ 0 : [length y | QueryName y <- qs, lower y `isPrefixOf` lower (x:xs)]
98+
mapIsInQueries (x:xs) = False : mapIsInQueries xs
99+
mapIsInQueries [] = []
100+
80101
unHTMLtargetItem :: Target -> Target
81102
unHTMLtargetItem target = target {targetItem = unHTML $ targetItem target}
82103

0 commit comments

Comments
 (0)