module XMonad.Actions.Search (
search,
SearchEngine(..),
searchEngine,
searchEngineF,
promptSearch,
promptSearchBrowser,
promptSearchBrowser',
selectSearch,
selectSearchBrowser,
isPrefixOf,
escape,
use,
intelligent,
(!>),
prefixAware,
namedEngine,
alpha,
amazon,
arXiv,
aur,
clojureDocs,
codesearch,
cratesIo,
deb,
debbts,
debpts,
dictionary,
duckduckgo,
ebay,
flora,
github,
google,
hackage,
homeManager,
hoogle,
images,
imdb,
lucky,
maps,
mathworld,
ncatlab,
nixos,
noogle,
openstreetmap,
protondb,
rosettacode,
rustStd,
scholar,
sourcehut,
stackage,
steam,
thesaurus,
vocabulary,
voidpgks_x86_64,
voidpgks_x86_64_musl,
wayback,
wikipedia,
wiktionary,
youtube,
zbmath,
multi,
Browser, Site, Query, Name, Search
) where
import Codec.Binary.UTF8.String (encode)
import Text.Printf
import XMonad (X (), liftIO)
import XMonad.Prompt (XPConfig (), XPrompt (showXPrompt, nextCompletion, commandToComplete),
getNextCompletion,
historyCompletionP, mkXPrompt)
import XMonad.Prelude (isAlphaNum, isAscii, isPrefixOf)
import XMonad.Prompt.Shell (getBrowser)
import XMonad.Util.Run (safeSpawn)
import XMonad.Util.XSelection (getSelection)
newtype Search = Search Name
instance XPrompt Search where
showXPrompt :: Search -> String
showXPrompt (Search String
name)= String
"Search [" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"]: "
nextCompletion :: Search -> String -> [String] -> String
nextCompletion Search
_ = String -> [String] -> String
getNextCompletion
commandToComplete :: Search -> String -> String
commandToComplete Search
_ String
c = String
c
escape :: String -> String
escape :: String -> String
escape = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
escapeURIChar
escapeURIChar :: Char -> String
escapeURIChar :: Char -> String
escapeURIChar Char
c | Char -> Bool
isAscii Char
c Bool -> Bool -> Bool
&& Char -> Bool
isAlphaNum Char
c = [Char
c]
| Bool
otherwise = (Word8 -> String) -> [Word8] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (String -> Word8 -> String
forall r. PrintfType r => String -> r
printf String
"%%%02X") ([Word8] -> String) -> [Word8] -> String
forall a b. (a -> b) -> a -> b
$ String -> [Word8]
encode [Char
c]
type Browser = FilePath
type Query = String
type Site = String -> String
type Name = String
data SearchEngine = SearchEngine Name Site
use :: SearchEngine -> Site
use :: SearchEngine -> String -> String
use (SearchEngine String
_ String -> String
engine) = String -> String
engine
search :: Browser -> Site -> Query -> X ()
search :: String -> (String -> String) -> String -> X ()
search String
browser String -> String
site String
query = String -> [String] -> X ()
forall (m :: * -> *). MonadIO m => String -> [String] -> m ()
safeSpawn String
browser [String -> String
site String
query]
searchEngine :: Name -> String -> SearchEngine
searchEngine :: String -> String -> SearchEngine
searchEngine String
name String
site = String -> (String -> String) -> SearchEngine
searchEngineF String
name (\String
s -> String
site String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> String
escape String
s)
searchEngineF :: Name -> Site -> SearchEngine
searchEngineF :: String -> (String -> String) -> SearchEngine
searchEngineF = String -> (String -> String) -> SearchEngine
SearchEngine
alpha, amazon, arXiv, aur, clojureDocs, codesearch, cratesIo, deb, debbts, debpts, dictionary, duckduckgo, ebay, flora,
github, google, hackage, homeManager, hoogle, images, imdb, lucky, maps, mathworld, ncatlab, nixos, noogle, openstreetmap, protondb,
rosettacode, rustStd, scholar, sourcehut, stackage, steam, thesaurus, vocabulary, voidpgks_x86_64, voidpgks_x86_64_musl, wayback,
wikipedia, wiktionary, youtube, zbmath :: SearchEngine
alpha :: SearchEngine
alpha = String -> String -> SearchEngine
searchEngine String
"alpha" String
"https://www.wolframalpha.com/input/?i="
amazon :: SearchEngine
amazon = String -> String -> SearchEngine
searchEngine String
"amazon" String
"https://www.amazon.com/s/ref=nb_sb_noss_2?url=search-alias%3Daps&field-keywords="
arXiv :: SearchEngine
arXiv = String -> (String -> String) -> SearchEngine
searchEngineF String
"arXiv" (\String
s -> String
"https://arxiv.org/search/?query=" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
s String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"&searchtype=all")
aur :: SearchEngine
aur = String -> String -> SearchEngine
searchEngine String
"aur" String
"https://aur.archlinux.org/packages?&K="
clojureDocs :: SearchEngine
clojureDocs = String -> String -> SearchEngine
searchEngine String
"clojureDocs" String
"https://clojuredocs.org/search?q="
codesearch :: SearchEngine
codesearch = String -> String -> SearchEngine
searchEngine String
"codesearch" String
"https://developers.google.com/s/results/code-search?q="
cratesIo :: SearchEngine
cratesIo = String -> String -> SearchEngine
searchEngine String
"cratesIo" String
"https://crates.io/search?q="
deb :: SearchEngine
deb = String -> String -> SearchEngine
searchEngine String
"deb" String
"https://packages.debian.org/"
debbts :: SearchEngine
debbts = String -> String -> SearchEngine
searchEngine String
"debbts" String
"https://bugs.debian.org/"
debpts :: SearchEngine
debpts = String -> String -> SearchEngine
searchEngine String
"debpts" String
"https://packages.qa.debian.org/"
dictionary :: SearchEngine
dictionary = String -> String -> SearchEngine
searchEngine String
"dict" String
"https://dictionary.reference.com/browse/"
duckduckgo :: SearchEngine
duckduckgo = String -> String -> SearchEngine
searchEngine String
"duckduckgo" String
"https://duckduckgo.com/?t=lm&q="
ebay :: SearchEngine
ebay = String -> String -> SearchEngine
searchEngine String
"ebay" String
"https://www.ebay.com/sch/i.html?_nkw="
flora :: SearchEngine
flora = String -> String -> SearchEngine
searchEngine String
"flora" String
"https://flora.pm/search?q="
github :: SearchEngine
github = String -> String -> SearchEngine
searchEngine String
"github" String
"https://github.com/search?q="
google :: SearchEngine
google = String -> String -> SearchEngine
searchEngine String
"google" String
"https://www.google.com/search?q="
hackage :: SearchEngine
hackage = String -> String -> SearchEngine
searchEngine String
"hackage" String
"https://hackage.haskell.org/package/"
homeManager :: SearchEngine
homeManager = String -> String -> SearchEngine
searchEngine String
"homeManager" String
"https://mipmip.github.io/home-manager-option-search/?query="
hoogle :: SearchEngine
hoogle = String -> String -> SearchEngine
searchEngine String
"hoogle" String
"https://hoogle.haskell.org/?hoogle="
images :: SearchEngine
images = String -> String -> SearchEngine
searchEngine String
"images" String
"https://images.google.fr/images?q="
imdb :: SearchEngine
imdb = String -> String -> SearchEngine
searchEngine String
"imdb" String
"https://www.imdb.com/find?s=all&q="
lucky :: SearchEngine
lucky = String -> String -> SearchEngine
searchEngine String
"lucky" String
"https://www.google.com/search?btnI&q="
maps :: SearchEngine
maps = String -> String -> SearchEngine
searchEngine String
"maps" String
"https://maps.google.com/maps?q="
mathworld :: SearchEngine
mathworld = String -> String -> SearchEngine
searchEngine String
"mathworld" String
"https://mathworld.wolfram.com/search/?query="
ncatlab :: SearchEngine
ncatlab = String -> String -> SearchEngine
searchEngine String
"ncatlab" String
"https://ncatlab.org/nlab/search?query="
nixos :: SearchEngine
nixos = String -> String -> SearchEngine
searchEngine String
"nixos" String
"https://search.nixos.org/packages?channel=unstable&from=0&size=200&sort=relevance&type=packages&query="
noogle :: SearchEngine
noogle = String -> (String -> String) -> SearchEngine
searchEngineF String
"noogle" (\String
s -> String
"https://noogle.dev/?search=" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
s String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"&page=1&to=any&from=any")
openstreetmap :: SearchEngine
openstreetmap = String -> String -> SearchEngine
searchEngine String
"openstreetmap" String
"https://www.openstreetmap.org/search?query="
protondb :: SearchEngine
protondb = String -> String -> SearchEngine
searchEngine String
"protondb" String
"https://www.protondb.com/search?q="
rosettacode :: SearchEngine
rosettacode = String -> String -> SearchEngine
searchEngine String
"rosettacode" String
"https://rosettacode.org/w/index.php?search="
rustStd :: SearchEngine
rustStd = String -> String -> SearchEngine
searchEngine String
"rustStd" String
"https://doc.rust-lang.org/std/index.html?search="
scholar :: SearchEngine
scholar = String -> String -> SearchEngine
searchEngine String
"scholar" String
"https://scholar.google.com/scholar?q="
sourcehut :: SearchEngine
sourcehut = String -> String -> SearchEngine
searchEngine String
"sourcehut" String
"https://sr.ht/projects?search="
stackage :: SearchEngine
stackage = String -> String -> SearchEngine
searchEngine String
"stackage" String
"https://www.stackage.org/lts/hoogle?q="
steam :: SearchEngine
steam = String -> String -> SearchEngine
searchEngine String
"steam" String
"https://store.steampowered.com/search/?term="
thesaurus :: SearchEngine
thesaurus = String -> String -> SearchEngine
searchEngine String
"thesaurus" String
"https://thesaurus.com/browse/"
vocabulary :: SearchEngine
vocabulary = String -> String -> SearchEngine
searchEngine String
"vocabulary" String
"https://www.vocabulary.com/search?q="
voidpgks_x86_64 :: SearchEngine
voidpgks_x86_64 = String -> String -> SearchEngine
searchEngine String
"voidpackages" String
"https://voidlinux.org/packages/?arch=x86_64&q="
voidpgks_x86_64_musl :: SearchEngine
voidpgks_x86_64_musl = String -> String -> SearchEngine
searchEngine String
"voidpackages" String
"https://voidlinux.org/packages/?arch=x86_64-musl&q="
wayback :: SearchEngine
wayback = String -> (String -> String) -> SearchEngine
searchEngineF String
"wayback" (String
"https://web.archive.org/web/*/"String -> String -> String
forall a. [a] -> [a] -> [a]
++)
wikipedia :: SearchEngine
wikipedia = String -> String -> SearchEngine
searchEngine String
"wiki" String
"https://en.wikipedia.org/wiki/Special:Search?go=Go&search="
wiktionary :: SearchEngine
wiktionary = String -> String -> SearchEngine
searchEngine String
"wikt" String
"https://en.wiktionary.org/wiki/Special:Search?go=Go&search="
youtube :: SearchEngine
youtube = String -> String -> SearchEngine
searchEngine String
"youtube" String
"https://www.youtube.com/results?search_type=search_videos&search_query="
zbmath :: SearchEngine
zbmath = String -> String -> SearchEngine
searchEngine String
"zbmath" String
"https://zbmath.org/?q="
multi :: SearchEngine
multi :: SearchEngine
multi = String -> SearchEngine -> SearchEngine
namedEngine String
"multi" (SearchEngine -> SearchEngine) -> SearchEngine -> SearchEngine
forall a b. (a -> b) -> a -> b
$ (SearchEngine -> SearchEngine -> SearchEngine)
-> [SearchEngine] -> SearchEngine
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 SearchEngine -> SearchEngine -> SearchEngine
(!>) [SearchEngine
alpha, SearchEngine
amazon, SearchEngine
aur, SearchEngine
codesearch, SearchEngine
deb, SearchEngine
debbts, SearchEngine
debpts, SearchEngine
dictionary, SearchEngine
duckduckgo, SearchEngine
ebay, SearchEngine
flora, SearchEngine
github, SearchEngine
hackage, SearchEngine
hoogle, SearchEngine
images, SearchEngine
imdb, SearchEngine
lucky, SearchEngine
maps, SearchEngine
mathworld, SearchEngine
ncatlab, SearchEngine
openstreetmap, SearchEngine
protondb, SearchEngine
rosettacode, SearchEngine
scholar, SearchEngine
sourcehut, SearchEngine
stackage, SearchEngine
steam, SearchEngine
thesaurus, SearchEngine
vocabulary, SearchEngine
voidpgks_x86_64, SearchEngine
voidpgks_x86_64_musl, SearchEngine
wayback, SearchEngine
wikipedia, SearchEngine
wiktionary, SearchEngine
youtube, SearchEngine -> SearchEngine
prefixAware SearchEngine
google]
intelligent :: SearchEngine -> SearchEngine
intelligent :: SearchEngine -> SearchEngine
intelligent (SearchEngine String
name String -> String
site) = String -> (String -> String) -> SearchEngine
searchEngineF String
name (\String
s -> if (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
takeWhile (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
':') String
s String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String
"http", String
"https", String
"ftp"] then String
s else String -> String
site String
s)
removeColonPrefix :: String -> String
removeColonPrefix :: String -> String
removeColonPrefix String
s = if Char
':' Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
s then Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
1 (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Char
':' Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/=) String
s else String
s
(!>) :: SearchEngine -> SearchEngine -> SearchEngine
(SearchEngine String
name1 String -> String
site1) !> :: SearchEngine -> SearchEngine -> SearchEngine
!> (SearchEngine String
name2 String -> String
site2) = String -> (String -> String) -> SearchEngine
searchEngineF (String
name1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
name2) (\String
s -> if (String
name1String -> String -> String
forall a. [a] -> [a] -> [a]
++String
":") String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
s then String -> String
site1 (String -> String
removeColonPrefix String
s) else String -> String
site2 String
s)
infixr 6 !>
prefixAware :: SearchEngine -> SearchEngine
prefixAware :: SearchEngine -> SearchEngine
prefixAware (SearchEngine String
name String -> String
site) = String -> (String -> String) -> SearchEngine
SearchEngine String
name (\String
s -> if (String
nameString -> String -> String
forall a. [a] -> [a] -> [a]
++String
":") String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf` String
s then String -> String
site (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
removeColonPrefix String
s else String -> String
site String
s)
namedEngine :: Name -> SearchEngine -> SearchEngine
namedEngine :: String -> SearchEngine -> SearchEngine
namedEngine String
name (SearchEngine String
_ String -> String
site) = String -> (String -> String) -> SearchEngine
searchEngineF String
name String -> String
site
promptSearchBrowser :: XPConfig -> Browser -> SearchEngine -> X ()
promptSearchBrowser :: XPConfig -> String -> SearchEngine -> X ()
promptSearchBrowser XPConfig
config String
browser (SearchEngine String
name String -> String
site) = do
ComplFunction
hc <- XPConfig -> (String -> Bool) -> X ComplFunction
historyCompletionP XPConfig
config (String
"Search [" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`)
Search -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
forall p.
XPrompt p =>
p -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
mkXPrompt (String -> Search
Search String
name) XPConfig
config ComplFunction
hc ((String -> X ()) -> X ()) -> (String -> X ()) -> X ()
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> String -> X ()
search String
browser String -> String
site
promptSearchBrowser' :: XPConfig -> Browser -> SearchEngine -> X ()
promptSearchBrowser' :: XPConfig -> String -> SearchEngine -> X ()
promptSearchBrowser' XPConfig
config String
browser (SearchEngine String
name String -> String
site) = do
ComplFunction
hc <- XPConfig -> (String -> Bool) -> X ComplFunction
historyCompletionP XPConfig
config (String
searchName String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isPrefixOf`)
Search -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
forall p.
XPrompt p =>
p -> XPConfig -> ComplFunction -> (String -> X ()) -> X ()
mkXPrompt (String -> Search
Search String
name) XPConfig
config ComplFunction
hc ((String -> X ()) -> X ()) -> (String -> X ()) -> X ()
forall a b. (a -> b) -> a -> b
$ String -> (String -> String) -> String -> X ()
search String
browser String -> String
site
where
searchName :: String
searchName = Search -> String
forall t. XPrompt t => t -> String
showXPrompt (String -> Search
Search String
name)
promptSearch :: XPConfig -> SearchEngine -> X ()
promptSearch :: XPConfig -> SearchEngine -> X ()
promptSearch XPConfig
config SearchEngine
engine = IO String -> X String
forall a. IO a -> X a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO String
getBrowser X String -> (String -> X ()) -> X ()
forall a b. X a -> (a -> X b) -> X b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \ String
browser -> XPConfig -> String -> SearchEngine -> X ()
promptSearchBrowser XPConfig
config String
browser SearchEngine
engine
selectSearchBrowser :: Browser -> SearchEngine -> X ()
selectSearchBrowser :: String -> SearchEngine -> X ()
selectSearchBrowser String
browser (SearchEngine String
_ String -> String
site) = String -> (String -> String) -> String -> X ()
search String
browser String -> String
site (String -> X ()) -> X String -> X ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< X String
forall (m :: * -> *). MonadIO m => m String
getSelection
selectSearch :: SearchEngine -> X ()
selectSearch :: SearchEngine -> X ()
selectSearch SearchEngine
engine = IO String -> X String
forall a. IO a -> X a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO String
getBrowser X String -> (String -> X ()) -> X ()
forall a b. X a -> (a -> X b) -> X b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
browser -> String -> SearchEngine -> X ()
selectSearchBrowser String
browser SearchEngine
engine