bhoogle 0.1.2.7 → 0.1.2.9
raw patch · 3 files changed
+96/−9 lines, 3 filesdep +typed-process
Dependencies added: typed-process
Files
- README.md +12/−0
- app/Main.hs +82/−8
- bhoogle.cabal +2/−1
README.md view
@@ -21,6 +21,18 @@ 1. Pressing **'s'** in the results list will toggle the sort order 1. Escape to exit 1. Search-ahead is enable for any type search longer than ~3 characters+ 1. When a result is selected `p` yanks the package name+ 1. When a result is selected `m` yanks the module name+++## Settings++Location: ~/.config/bhoogle/bhoogle.conf ++Eg:++ yank=xclip+ yankArgs=-selection c Note that the version described in the [blog](http://www.andrevdm.com/posts/2018-01-15-bhoogle.html) is on the [blog](https://github.com/andrevdm/bhoogle/tree/blog) branch.
app/Main.hs view
@@ -8,9 +8,12 @@ import Protolude import Control.Lens ((^.), (.~), (%~)) import Control.Lens.TH (makeLenses)+import qualified Data.Map as Map import qualified Data.List as Lst import qualified Data.Time as Tm import qualified Data.Text as Txt+import qualified Data.Text.Encoding as TxtE+import qualified Data.ByteString as BS import qualified Data.Vector as Vec import Brick ((<+>), (<=>)) import qualified Brick as B@@ -27,7 +30,8 @@ import System.FilePath ((</>)) import qualified System.Directory as Dir import qualified Hoogle as H-+import qualified System.Process.Typed as PT+import qualified Data.ByteString.Lazy as BSL -- | Events that can be sent@@ -48,14 +52,16 @@ -- | State of the brick app. Contains the controls and any other required state-data BrickState = BrickState { _stEditType :: !(BE.Editor Text Name) -- ^ Editor for the type to search for- , _stEditText :: !(BE.Editor Text Name) -- ^ Editor for a text search in the results- , _stTime :: !Tm.LocalTime -- ^ The current time- , _stFocus :: !(BF.FocusRing Name) -- ^ Focus ring - a circular list of focusable controls- , _stResults :: [H.Target] -- ^ The last set of search results from hoohle+data BrickState = BrickState { _stEditType :: !(BE.Editor Text Name) -- ^ Editor for the type to search for+ , _stEditText :: !(BE.Editor Text Name) -- ^ Editor for a text search in the results+ , _stTime :: !Tm.LocalTime -- ^ The current time+ , _stFocus :: !(BF.FocusRing Name) -- ^ Focus ring - a circular list of focusable controls+ , _stResults :: [H.Target] -- ^ The last set of search results from hoohle , _stResultsList :: !(BL.List Name H.Target) -- ^ List for the search results , _stSortResults :: SortBy -- ^ Current sort order for the results , _stDbPath :: FilePath -- ^ Hoogle DB path+ , _yankCommand :: Text -- ^ Command to run to copy text to the clipboard + , _yankArgs :: Text -- ^ Args for the yank command } makeLenses ''BrickState@@ -103,6 +109,9 @@ -- Initial current time value t <- getTime + -- Settings+ settings <- loadSettings+ -- Construct the initial state values let st = BrickState { _stEditType = BE.editor TypeSearch (Just 1) "" , _stEditText = BE.editor TextSearch (Just 1) ""@@ -112,6 +121,8 @@ , _stResults = [] , _stSortResults = SortNone , _stDbPath = dbPath+ , _yankCommand = Map.findWithDefault "xclip" "yank" settings+ , _yankArgs = Map.findWithDefault "" "yankArgs" settings } -- And run brick@@ -191,7 +202,12 @@ let sorter = if sortDir == SortDec then (Lst.sortBy $ flip compareType) else (Lst.sortBy compareType) in B.continue . filterResults $ st & stResults %~ sorter & stSortResults .~ sortDir-+ K.KChar 'p' -> do+ let selected = BL.listSelectedElement $ st ^. stResultsList+ B.suspendAndResume (yankPackage st selected)+ K.KChar 'm' -> do+ let selected = BL.listSelectedElement $ st ^. stResultsList+ B.suspendAndResume (yankModule st selected) _ -> do -- Let the list handle all other events -- Using handleListEventVi which adds vi-style keybindings for navigation@@ -212,6 +228,28 @@ liftIO $ searchHoogle (st' ^. stDbPath) (Txt.strip . Txt.concat $ BE.getEditContents (st' ^. stEditType)) +yank :: (H.Target -> Maybe Text) -> BrickState -> Maybe (Int, H.Target) -> IO BrickState+yank getText st selected = + case getText <<$>> selected of+ Just (_, Just s') -> do+ let cmd = (st ^. yankCommand) <> " " <> (st ^. yankArgs)+ PT.runProcess_ $ PT.setStdin (PT.byteStringInput (BSL.fromStrict . TxtE.encodeUtf8 $ s')) (PT.shell (Txt.unpack cmd))+ pure st++ _ ->+ pure st+++yankPackage :: BrickState -> Maybe (Int, H.Target) -> IO BrickState+yankPackage st selected = + yank (\t -> Txt.pack . fst <$> H.targetPackage t) st selected+++yankModule :: BrickState -> Maybe (Int, H.Target) -> IO BrickState+yankModule st selected = + yank (\t -> Txt.pack . fst <$> H.targetModule t) st selected++ -- | Search ahead for type strings longer than 3 chars. searchAhead :: (BrickState -> IO [H.Target]) -> BrickState -> IO BrickState searchAhead search st =@@ -342,7 +380,7 @@ -- | Search hoogle using the default hoogle database searchHoogle :: FilePath -> Text -> IO [H.Target]-searchHoogle path f = do+searchHoogle path f = H.withDatabase path (\x -> pure $ H.searchDatabase x (Txt.unpack f)) @@ -375,3 +413,39 @@ stripTags ('<' : xs) = stripTags $ drop 1 $ dropWhile (/= '>') xs stripTags (x : xs) = x : stripTags xs +----------------------------------------------------------------------------------------------------++loadSettings :: IO (Map Text Text)+loadSettings = do+ p <- getSettingsFilePath++ Dir.doesFileExist p >>= \case+ True -> do+ cfgLines1 <- Txt.lines . TxtE.decodeUtf8 <$> BS.readFile p+ let cfgLines2 = Txt.strip <$> cfgLines1+ let cfgLines3 = filter (not . Txt.isPrefixOf "#") cfgLines2+ let cfg1 = Txt.breakOn "=" <$> cfgLines3+ let cfg2 = filter (not . Txt.null . snd) cfg1+ let cfg3 = (\(k, v) -> (Txt.strip k, Txt.strip . Txt.drop 1 $ v)) <$> cfg2+ pure $ Map.fromList cfg3+ False ->+ pure Map.empty++saveSettings :: Map Text Text -> IO ()+saveSettings settings = do+ p <- getSettingsFilePath+ let ss = Txt.intercalate "\n" $ (\(k, v) -> k <> "=" <> v) <$> Map.toList settings+ BS.writeFile p . TxtE.encodeUtf8 $ ss+++getSettingsFilePath :: IO FilePath+getSettingsFilePath = do+ p <- getSettingsRootPath+ pure $ p </> "bhoogle.conf"+++getSettingsRootPath :: IO FilePath+getSettingsRootPath = do+ p <- Dir.getXdgDirectory Dir.XdgConfig "bhoogle"+ Dir.createDirectoryIfMissing True p+ pure p
bhoogle.cabal view
@@ -1,5 +1,5 @@ name: bhoogle-version: 0.1.2.7+version: 0.1.2.9 synopsis: Simple terminal GUI for local hoogle. description: bhoogle is a terminal GUI layer over local hoogle. It provides search ahead and sub-string filtering in addition to the usual type-search. homepage: https://github.com/andrevdm/bhoogle#readme@@ -31,6 +31,7 @@ , bytestring >= 0.10.8.1 , time >= 1.6.0.1 , hoogle >= 5.0.14+ , typed-process >= 0.2.2 default-language: Haskell2010 source-repository head