shortcut-links-0.1.0.0: src/ShortcutLinks/All.hs
{-# LANGUAGE
OverloadedStrings,
DeriveFunctor,
ViewPatterns
#-}
module ShortcutLinks.All
(
Result(..),
Shortcut,
allShortcuts,
-- * Encyclopedias
wikipedia, tvtropes,
-- * Social networks
facebook, vk, googleplus,
-- * Microblogs
twitter, juick,
-- * Major search engines
google, duckduckgo, yandex, baidu,
-- * Programming language libraries
npm, jam, rubygems, pypi, metacpanPod, metacpanRelease, hackage, cargo,
pub, hex, cran, swiprolog, dub, bpkg, pear,
-- * Code hosting
github, gitlab, bitbucket,
-- * OS packages
-- ** Mobile
googleplay,
-- ** Windows
chocolatey,
-- ** OS X
braumeister,
-- ** Linux
debian, aur, mint, fedora, gentoo, opensuse,
-- * Addons
-- ** Text editors
marmalade, melpa, elpa, packagecontrol, atomPackage, atomTheme, jedit, vim,
-- ** Browsers
operaExt, operaTheme, firefox, chrome,
-- * Manuals
ghcExt,
-- * Standards and databases
rfc, ecma, cve,
)
where
-- General
import Data.Monoid
import Control.Applicative
import Control.Monad
import Data.Maybe
-- Text
import qualified Data.Text as T
import Data.Text (Text)
import Data.Char
-- shortcut-links
import ShortcutLinks.Utils
data Result a = Failure String | Warning [String] a | Success a
deriving (Show, Functor)
instance Applicative Result where
pure = return
(<*>) = ap
instance Monad Result where
fail = Failure
return = Success
Failure x >>= _ = Failure x
Warning wa a >>= f = case f a of
Success b -> Warning wa b
Warning wb b -> Warning (wa ++ wb) b
Failure x -> Failure x
Success a >>= f = f a
warn :: String -> Result ()
warn s = Warning [s] ()
type Shortcut = Maybe Text -> Text -> Result Text
-- | A list of all functions included in this module, together with suggested
-- names for them.
allShortcuts :: [([Text], Shortcut)]
allShortcuts =
let (.=) names func = (T.words names, func)
in [
-- encyclopedias
"w wikipedia" .= wikipedia,
"tvt tvtropes" .= tvtropes,
-- social networks
"fb facebook" .= facebook,
"vk vkontakte" .= vk,
"gp gplus googleplus" .= googleplus,
-- microblogs
"t twitter" .= twitter,
"juick" .= juick,
-- search engines
"google" .= google,
"ddg duckduckgo" .= duckduckgo,
"yandex" .= yandex,
"baidu" .= baidu,
-- programming language libraries
"npm" .= npm,
"jam" .= jam,
"gem" .= rubygems,
"pypi" .= pypi,
"cpan" .= metacpanPod,
"cpan-r" .= metacpanRelease,
"hackage" .= hackage,
"cargo" .= cargo,
"pub" .= pub,
"hex" .= hex,
"cran" .= cran,
"swiprolog" .= swiprolog,
"dub" .= dub,
"bpkg" .= bpkg,
"pear" .= pear,
-- code hosting
"gh github" .= github,
"gitlab" .= gitlab,
"bitbucket" .= bitbucket,
-- OS
"gplay googleplay" .= googleplay,
"chocolatey" .= chocolatey,
"brew" .= braumeister,
-- OS – Linux
"debian" .= debian,
"aur" .= aur,
"mint" .= mint,
"fedora" .= fedora,
"gentoo" .= gentoo,
"opensuse" .= opensuse,
-- text editors
"marmalade" .= marmalade,
"melpa" .= melpa,
"elpa" .= elpa,
"sublime" .= packagecontrol,
"atom" .= atomPackage,
"atom-theme" .= atomTheme,
"jedit" .= jedit,
"vim" .= vim,
-- browsers
"opera" .= operaExt,
"opera-theme" .= operaTheme,
"firefox" .= firefox,
"chrome" .= chrome,
-- manuals
"ghc-ext" .= ghcExt,
-- standards and databases
"rfc" .= rfc,
"ecma" .= ecma,
"cve" .= cve ]
-- | <https://facebook.com Facebook>
--
-- Link example:
-- @[green](\@fb)@ →
-- <https://facebook.com/green>
facebook :: Shortcut
facebook _ q = return $ "https://facebook.com/" <> q
-- | <https://vk.com Vkontakte> (Вконтакте)
--
-- Link example (username):
-- @[green](\@vk)@ →
-- <https://vk.com/green>
--
-- Link example (ID):
--
-- @[1337](\@vk)@ →
-- <https://vk.com/id1337>
vk :: Shortcut
vk _ q = return $ "https://vk.com/" <> q'
where q' = if not (T.null q) && isDigit (T.head q) then "id" <> q else q
-- | <https://plus.google.com Google+>
--
-- Link example (username):
-- @[SergeyBrin](\@gp)@ →
-- <https://plus.google.com/+SergeyBrin SergeyBrin>
--
-- Link example (username with @+@):
-- @[+SergeyBrin](\@gp)@ →
-- <https://plus.google.com/+SergeyBrin +SergeyBrin>
--
-- Link example (full name – will just be concatenated):
-- @[Sergey Brin](\@gp)@ →
-- <https://plus.google.com/+SergeyBrin Sergey Brin>
--
-- Link example (ID):
-- @[Sergey Brin](\@gp:109813896768294978296)@ →
-- <https://plus.google.com/109813896768294978296 Sergey Brin>
--
-- Link example (hashtag):
-- @[#Australia](\@gp)@ →
-- <https://plus.google.com/explore/Australia #Australia>
googleplus :: Shortcut
googleplus _ q
| T.null q = return $ url
| T.head q == '#' = return $ format "{}/explore/{}" url (T.tail q)
| T.head q == '+' = return $ format "{}/{}" url q
| T.all isDigit q = return $ format "{}/{}" url q
| otherwise = return $ format "{}/+{}" url (T.concat (T.words q))
where url = "https://plus.google.com"
-- | <https://twitter.com Twitter>
--
-- Link example (username):
-- @[kmett](\@t)@ →
-- <https://twitter.com/kmett kmett>
--
-- Link example (username with @\@@):
-- @[\@kmett](\@t)@ →
-- <https://twitter.com/kmett \@kmett>
--
-- Link example (hashtag):
-- @[#haskell](\@t)@ →
-- <https://twitter.com/hashtag/haskell #haskell>
twitter :: Shortcut
twitter _ q
| T.null q = return $ url
| T.head q == '#' = return $ format "{}/hashtag/{}" url (T.tail q)
| T.head q == '@' = return $ format "{}/{}" url (T.tail q)
| otherwise = return $ format "{}/{}" url q
where url = "https://twitter.com"
-- | <https://juick.com Juick>
--
-- Link example (username):
-- @[thefish](\@juick)@ →
-- <https://juick.com/thefish/ thefish>
--
-- Link example (username with @\@@):
-- @[\@thefish](\@juick)@ →
-- <https://juick.com/thefish/ \@thefish>
--
-- Link example (tag):
-- @[*Haskell](\@juick)@ →
-- <https://juick.com/tag/Haskell *Haskell>
juick :: Shortcut
juick _ q
| T.null q = return $ url
| T.head q == '*' = return $ format "{}/tag/{}" url (T.tail q)
| T.head q == '@' = return $ format "{}/{}" url (T.tail q)
| otherwise = return $ format "{}/{}" url q
where url = "https://juick.com"
-- | <https://google.com Google>
--
-- Link example:
-- @[random query](\@google)@ →
-- <https://www.google.com/search?nfpr=1&q=random+query random query>
google :: Shortcut
google _ q = return $
"https://google.com/search?nfpr=1&q=" <> replaceSpaces '+' q
-- | <https://duckduckgo.com Duckduckgo>
--
-- Link example:
-- @[random query](\@ddg)@ →
-- <https://duckduckgo.com/?q=random+query random query>
duckduckgo :: Shortcut
duckduckgo _ q = return $ "https://duckduckgo.com/?q=" <> replaceSpaces '+' q
-- | <http://yandex.ru Yandex> (Russian search engine)
--
-- Link example:
-- @[random query](\@yandex)@ →
-- <http://yandex.ru/search/?noreask=1&text=random+query random query>
yandex :: Shortcut
yandex _ q = return $
"http://yandex.ru/search/?noreask=1&text=" <> replaceSpaces '+' q
-- | <http://baidu.com Baidu> (Chinese search engine)
--
-- Link example:
-- @[random query](\@baidu)@ →
-- <http://baidu.com/s?nojc=1&wd=random+query random query>
baidu :: Shortcut
baidu _ q = return $ "http://baidu.com/s?nojc=1&wd=" <> replaceSpaces '+' q
-- | __Node.js__ – <https://npmjs.com NPM>
--
-- Link example:
-- @[markdown](\@npm)@ →
-- <https://www.npmjs.com/package/markdown markdown>
npm :: Shortcut
npm _ q = return $ "https://npmjs.com/package/" <> q
-- | __Javascript__ – <http://jamjs.org/packages/#/ Jam>
--
-- Link example:
-- @[pagedown](\@jam)@ →
-- <http://jamjs.org/packages/#/details/pagedown pagedown>
jam :: Shortcut
jam _ q = return $ "http://jamjs.org/packages/#/details/" <> q
-- | __Ruby__ – <https://rubygems.org RubyGems.org>
--
-- Link example:
-- @[github-markdown](\@gem)@ →
-- <https://rubygems.org/gems/github-markdown github-markdown>
rubygems :: Shortcut
rubygems _ q = return $ "https://rubygems.org/gems/" <> q
-- | __Python__ – <https://pypi.python.org/pypi PyPI>
--
-- Link example:
-- @[Markdown](\@pypi)@ →
-- <https://pypi.python.org/pypi/Markdown Markdown>
pypi :: Shortcut
pypi _ q = return $ "https://pypi.python.org/pypi/" <> q
-- | __Perl__ – <https://metacpan.org MetaCPAN> (by module)
--
-- Link example:
-- @[Text::Markdown](\@cpan)@ →
-- <https://metacpan.org/pod/Text::Markdown Text::Markdown>
metacpanPod :: Shortcut
metacpanPod _ q = return $ "https://metacpan.org/pod/" <> q
-- | __Perl__ – <https://metacpan.org MetaCPAN> (by release)
--
-- Link example:
-- @[Text-Markdown](\@cpan-r)@ →
-- <https://metacpan.org/release/Text-Markdown Text-Markdown>
metacpanRelease :: Shortcut
metacpanRelease _ q = return $ "https://metacpan.org/release/" <> q
-- | __Haskell__ – <https://hackage.haskell.org Hackage>
--
-- Link example:
-- @[cmark](\@hackage)@ →
-- <https://hackage.haskell.org/package/cmark cmark>
hackage :: Shortcut
hackage _ q = return $ "https://hackage.haskell.org/package/" <> q
-- | __Rust__ – <https://crates.io Cargo>
--
-- Link example:
-- @[hoedown](\@cargo)@ →
-- <https://crates.io/crates/hoedown hoedown>
cargo :: Shortcut
cargo _ q = return $ "https://crates.io/crates/" <> q
-- | __PHP__ – <http://pear.php.net PEAR>
--
-- Link example:
-- @[Text_Wiki_Doku](\@pear)@ →
-- <http://pear.php.net/package/Text_Wiki_Doku Text_Wiki_Doku>
pear :: Shortcut
pear _ q = return $ "http://pear.php.net/package/" <> q
-- | __Dart__ – <https://pub.dartlang.org pub>
--
-- Link example:
-- @[md_proc](\@pub)@ →
-- <https://pub.dartlang.org/packages/md_proc md_proc>
pub :: Shortcut
pub _ q = return $ "https://pub.dartlang.org/packages/" <> q
-- | __R__ – <http://cran.r-project.org/web/packages/ CRAN>
--
-- Link example:
-- @[markdown](\@cran)@ →
-- <http://cran.r-project.org/web/packages/markdown markdown>
cran :: Shortcut
cran _ q = return $ "http://cran.r-project.org/web/packages/" <> q
-- | __Erlang__ – <https://hex.pm Hex>
--
-- Link example:
-- @[earmark](\@hex)@ →
-- <https://hex.pm/packages/earmark earmark>
hex :: Shortcut
hex _ q = return $ "https://hex.pm/packages/" <> q
-- | __SWI-Prolog__ – <http://www.swi-prolog.org/pack/list packages>
--
-- Link example:
-- @[markdown](\@swiprolog)@ →
-- <http://www.swi-prolog.org/pack/list?p=markdown markdown>
swiprolog :: Shortcut
swiprolog _ q = return $ "http://www.swi-prolog.org/pack/list?p=" <> q
-- | __D__ – <http://code.dlang.org DUB>
--
-- Link example:
-- @[dmarkdown](\@dub)@ →
-- <http://code.dlang.org/packages/dmarkdown dmarkdown>
dub :: Shortcut
dub _ q = return $ "http://code.dlang.org/packages/" <> q
-- | __Bash__ – <http://bpkg.io bpkg>
--
-- Link example:
-- @[markdown](\@bpkg)@ →
-- <http://www.bpkg.io/pkg/markdown markdown>
bpkg :: Shortcut
bpkg _ q = return $ "http://bpkg.io/pkg/" <> q
-- | <https://github.com Github>
--
-- Link example:
-- @[aelve/shortcut-links](\@gh)@ →
-- <https://github.com/aelve/shortcut-links aelve/shortcut-links>
--
-- The repository owner can also be given as an option:
--
-- @[shortcut-links](\@gh(aelve))@ →
-- <https://github.com/aelve/shortcut-links shortcut-links>
github :: Shortcut
github mbOwner q = case mbOwner of
Nothing -> return $ format "https://github.com/{}" q
Just owner -> return $ format "https://github.com/{}/{}" owner q
-- | <https://bitbucket.org Bitbucket>
--
-- Link example:
-- @[bos/text](\@bitbucket)@ →
-- <https://bitbucket.org/bos/text bos/text>
--
-- The repository owner can also be given as an option:
--
-- @[text](\@bitbucket(bos))@ →
-- <https://bitbucket.org/bos/text text>
bitbucket :: Shortcut
bitbucket mbOwner q = case mbOwner of
Nothing -> return $ format "https://bitbucket.org/{}" q
Just owner -> return $ format "https://bitbucket.org/{}/{}" owner q
-- | <https://gitlab.com Gitlab>
--
-- Link example:
-- @[learnyou/lysa](\@gitlab)@ →
-- <https://gitlab.com/learnyou/lysa learnyou/lysa>
--
-- The repository owner can also be given as an option:
--
-- @[lysa](\@gitlab(learnyou))@ →
-- <https://gitlab.com/learnyou/lysa lysa>
--
-- Note that links like <https://gitlab.com/owner> work but are going to be
-- automatically redirected to either <https://gitlab.com/u/owner> or
-- <https://gitlab.com/groups/owner>, depending on whether it's a user or a
-- team. So, it's a case when the “links have to look as authentic as
-- possible” principle is violated (but c'mon, this “u” thing looks ugly
-- anyway).
gitlab :: Shortcut
gitlab mbOwner q = case mbOwner of
Nothing -> return $ format "https://gitlab.com/{}" q
Just owner -> return $ format "https://gitlab.com/{}/{}" owner q
-- | __Android__ – <https://play.google.com Google Play> (formerly Play Market)
--
-- Link example:
-- @[Opera Mini](\@gplay:com.opera.mini.native)@ →
-- <https://play.google.com/store/apps/details?id=com.opera.mini.native Opera Mini>
googleplay :: Shortcut
googleplay _ q = return $ "https://play.google.com/store/apps/details?id=" <> q
-- | <http://braumeister.org Braumeister> (Homebrew formulas)
--
-- Link example:
-- @[multimarkdown](\@brew)@ →
-- <http://braumeister.org/formula/multimarkdown multimarkdown>
braumeister :: Shortcut
braumeister _ q = return $ "http://braumeister.org/formula/" <> q
-- | <https://chocolatey.org Chocolatey>
--
-- Link example:
-- @[Opera](\@chocolatey)@ →
-- <https://chocolatey.org/packages/Opera Opera>
chocolatey :: Shortcut
chocolatey _ q = return $ "https://chocolatey.org/packages/" <> q
-- | __Debian__ – <https://debian.org/distrib/packages packages>
--
-- Link example (stable distribution):
-- @[ghc](\@debian)@ →
-- <https://packages.debian.org/stable/ghc ghc>
--
-- Link example (experimental distribution, but could be any other):
-- @[ghc](\@debian(experimental))@ →
-- <https://packages.debian.org/experimental/ghc ghc>
debian :: Shortcut
debian mbDist q = return $ format "https://packages.debian.org/{}/{}" dist q
where
dist = fromMaybe "stable" mbDist
-- | __Arch Linux__ – <https://aur.archlinux.org AUR> (“user repository”)
--
-- Link example:
-- @[ghc-git](\@aur)@ →
-- <https://aur.archlinux.org/packages/ghc-git ghc-git>
aur :: Shortcut
aur _ q = return $ "https://aur.archlinux.org/packages/" <> q
-- | __Gentoo__ – <https://packages.gentoo.org packages>
--
-- Link example:
-- @[dev-lang/ghc](\@gentoo)@ →
-- <https://packages.gentoo.org/package/dev-lang/ghc dev-lang/ghc>
--
-- Link example (category as an option):
-- @[ghc](\@gentoo(dev-lang))@ →
-- <https://packages.gentoo.org/package/dev-lang/ghc ghc>
--
-- Note that if you don't specify any category, the link would still work –
-- but there are a lot of packages with overlapping names (like “ace”, “csv”,
-- “http”), and such links would lead to search pages listing several
-- packages. So, it's better to include categories.
gentoo :: Shortcut
gentoo mbCat q = return $ "https://packages.gentoo.org/package/" <> pkg
where
pkg = case mbCat of
Nothing -> q
Just cat -> cat <> "/" <> q
-- | __openSUSE__ – <http://software.opensuse.org packages>
--
-- Link example:
-- @[ghc](\@opensuse)@ →
-- <http://software.opensuse.org/package/ghc ghc>
opensuse :: Shortcut
opensuse _ q = return $ "http://software.opensuse.org/package/" <> q
-- | __Linux Mint__ – <http://community.linuxmint.com/software/browse packages>
--
-- Link example:
-- @[ghc](\@mint)@ →
-- <http://community.linuxmint.com/software/view/ghc ghc>
mint :: Shortcut
mint _ q = return $ "http://community.linuxmint.com/software/view/" <> q
-- | __Fedora__ – <https://admin.fedoraproject.org/pkgdb packages>
--
-- Link example:
-- @[ghc](\@fedora)@ →
-- <https://admin.fedoraproject.org/pkgdb/package/ghc ghc>
fedora :: Shortcut
fedora _ q = return $ "https://admin.fedoraproject.org/pkgdb/package/" <> q
-- | __Emacs__ – <https://marmalade-repo.org Marmalade>
--
-- Link example:
-- @[markdown-mode](\@marmalade)@ →
-- <https://marmalade-repo.org/packages/markdown-mode markdown-mode>
marmalade :: Shortcut
marmalade _ q = return $ "https://marmalade-repo.org/packages/" <> q
-- | __Emacs__ – <http://melpa.org MELPA>
--
-- Link example:
-- @[markdown-mode](\@melpa)@ →
-- <http://melpa.org/#/markdown-mode markdown-mode>
melpa :: Shortcut
melpa _ q = return $ "http://melpa.org/#/" <> q
-- | __Emacs__ – <https://elpa.gnu.org ELPA>
--
-- Link example:
-- @[undo-tree](\@elpa)@ →
-- <https://elpa.gnu.org/packages/undo-tree.html undo-tree>
elpa :: Shortcut
elpa _ q = return $ format "https://elpa.gnu.org/packages/{}.html" q
-- | __Sublime Text__ – <https://packagecontrol.io Package Control>
--
-- Link example:
-- @[MarkdownEditing](\@sublime)@ →
-- <https://packagecontrol.io/packages/MarkdownEditing MarkdownEditing>
packagecontrol :: Shortcut
packagecontrol _ q = return $ "https://packagecontrol.io/packages/" <> q
-- | __Atom__ – <https://atom.io/packages packages>
--
-- Link example:
-- @[tidy-markdown](\@atom)@ →
-- <https://atom.io/packages/tidy-markdown tidy-markdown>
atomPackage :: Shortcut
atomPackage _ q = return $ "https://atom.io/packages/" <> q
-- | __Atom__ – <https://atom.io/themes themes>
--
-- Link example:
-- @[atom-material-ui](\@atom-theme)@ →
-- <https://atom.io/themes/atom-material-ui atom-material-ui>
atomTheme :: Shortcut
atomTheme _ q = return $ "https://atom.io/themes/" <> q
-- | __jEdit__ – <http://plugins.jedit.org packages>
--
-- Link example:
-- @[MarkdownPlugin](\@jedit)@ →
-- <http://plugins.jedit.org/plugins/?MarkdownPlugin MarkdownPlugin>
jedit :: Shortcut
jedit _ q = return $ "http://plugins.jedit.org/plugins/?" <> q
-- | __Vim__ – <http://www.vim.org/scripts/ scripts>
--
-- Link example (ID):
-- @[haskell.vim](\@vim:2062)@ →
-- <http://www.vim.org/scripts/script.php?script_id=2062 haskell.vim>
vim :: Shortcut
vim _ q = return $ "http://www.vim.org/scripts/script.php?script_id=" <> q
-- | __Opera__ – <https://addons.opera.com/extensions/ extensions>
--
-- Link example:
-- @[Amazon](\@opera:amazon-for-opera)@ →
-- <https://addons.opera.com/extensions/details/amazon-for-opera Amazon>
operaExt :: Shortcut
operaExt _ q = return $ "https://addons.opera.com/extensions/details/" <> q
-- | __Opera__ – <https://addons.opera.com/themes/ themes>
--
-- Link example:
-- @[Space theme](\@opera-theme:space-15)@ →
-- <https://addons.opera.com/en/themes/details/space-15 Space theme>
operaTheme :: Shortcut
operaTheme _ q = return $ "https://addons.opera.com/themes/details/" <> q
-- | __Firefox__ – <https://addons.mozilla.org/firefox Add-ons> (extensions, themes)
--
-- Link example:
-- @[tree-style-tab]@ →
-- <https://addons.mozilla.org/firefox/addon/tree-style-tab Tree Style Tab>
firefox :: Shortcut
firefox _ q = return $ "https://addons.mozilla.org/firefox/addon/" <> q
-- | __Chrome__ – <https://chrome.google.com/webstore Chrome Web Store> (extensions, apps, themes)
--
-- Link example:
-- @[hdokiejnpimakedhajhdlcegeplioahd]@ →
-- <https://chrome.google.com/webstore/detail/hdokiejnpimakedhajhdlcegeplioahd LastPass>
chrome :: Shortcut
chrome _ q = return $ "https://chrome.google.com/webstore/detail/" <> q
-- | <https://www.haskell.org/ghc/ GHC> (Glasgow Haskell Compiler) extensions
--
-- Link example:
-- @[ViewPatterns](\@ghc-ext)@ →
-- <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/syntax-extns.html#view-patterns ViewPatterns>
ghcExt :: Shortcut
ghcExt _ ext = case lookup ext ghcExtsList of
Nothing -> fail (format "unknown GHC extension '{}'" ext)
Just link -> return link
-- | <https://www.ietf.org/rfc.html RFCs>
--
-- Link example:
-- @[RFC 2026](\@rfc)@ →
-- <https://tools.ietf.org/html/rfc2026 RFC 2026>
--
-- Precise format of recognised text: optional “rfc” (case-insensitive), then
-- arbitrary amount of spaces and punctuation (or nothing), then the
-- number. Examples: “RFC 2026”, “RFC-2026”, “rfc2026”, “rfc #2026”, “2026”,
-- “#2026”.
rfc :: Shortcut
rfc _ x = do
let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "rfc" x)
-- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC
-- 7.4, which Pandoc has to be compatible with.
unless (T.all isDigit n) $
warn "non-digits in RFC number"
when (T.null n) $
warn "no RFC number"
let n' = T.dropWhile (== '0') n `orElse` "0"
return ("https://tools.ietf.org/html/rfc" <> n')
-- | <http://ecma-international.org/publications/index.html Ecma standards and technical reports>
--
-- Link example (standard):
-- @[ECMA-262](\@ecma)@ →
-- <http://www.ecma-international.org/publications/standards/Ecma-262.htm ECMA-262>
--
-- Link example (technical report):
-- @[TR/71](\@ecma)@ →
-- <http://ecma-international.org/publications/techreports/E-TR-071.htm TR/71>
--
-- Precise format of recognised text for standards: optional “ECMA”
-- (case-insensitive), then arbitrary amount of spaces and punctuation (or
-- nothing), then the number. Examples: “ECMA-262”, “ECMA 262”, “ecma262”,
-- “ECMA #262”, “262”, “#262”.
--
-- Format for technical reports is the same, except that “TR” (instead of
-- “ECMA”) is not optional (so, if there's only a number given, it's
-- considered a standard and not a technical report).
ecma :: Shortcut
ecma _ q = do
-- TODO: move dropSeparators to Utils and use it in 'rfc' and 'cve'
let dropSeparators = T.dropWhile (not . isAlphaNum)
let (dropSeparators -> mbNum, isTR) = case stripPrefixCI "tr" q of
Nothing -> (tryStripPrefixCI "ecma" q, False)
Just q' -> (q', True)
-- We don't use 'readMaybe' here because 'readMaybe' isn't available in GHC
-- 7.4, which Pandoc has to be compatible with.
unless (T.all isDigit mbNum) $
warn "non-digits in ECMA standard number"
when (T.null mbNum) $
warn "no ECMA standard number"
-- The number has to have at least 3 digits.
let num = T.justifyRight 3 '0' mbNum
url = "http://ecma-international.org/publications" :: Text
return $ if isTR
then format "{}/techreports/E-TR-{}.htm" url num
else format "{}/standards/Ecma-{}.htm" url num
-- | <http://cve.mitre.org CVEs> (Common Vulnerabilities and Exposures)
--
-- Link example:
-- @[CVE-2014-10001](\@cve)@ →
-- <http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-10001>
--
-- Precise format of recognised text: optional “cve” (case-insensitive), then
-- arbitrary amount of spaces and punctuation (or nothing), then the year,
-- ‘-’, and a number. Examples: “CVE-2014-10001”, “cve 2014-10001”,
-- “2014-10001”.
cve :: Shortcut
cve _ x = do
let n = T.dropWhile (not . isAlphaNum) (tryStripPrefixCI "cve" x)
unless (T.length n >= 9) $
warn "CVE-ID is too short"
let isValid = and [
T.length n >= 9,
T.all isDigit (T.take 4 n),
T.index n 4 == '-',
T.all isDigit (T.drop 5 n) ]
unless isValid $
warn "CVE-ID doesn't follow the <year>-<digits> format"
return ("http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-" <> n)
-- | <https://wikipedia.org/ Wikipedia>
--
-- Link example (English Wikipedia):
-- @[grey-headed flying fox](\@w)@ →
-- <https://en.wikipedia.org/wiki/Grey-headed_flying_fox>
--
-- Link example (Russian Wikipedia, but any language code can be used):
-- @[Haskell](\@w(ru))@ →
-- <https://ru.wikipedia.org/wiki/Haskell>
wikipedia :: Shortcut
wikipedia mbLang q = return $
format "https://{}.wikipedia.org/wiki/{}" lang q'
where
lang = fromMaybe "en" mbLang
q' = titleFirst (replaceSpaces '_' q)
-- | <http://tvtropes.org TV Tropes>
--
-- Link example (trope):
-- @[so bad, it's good](\@tvtropes)@ →
-- <http://tvtropes.org/pmwiki/pmwiki.php/Main/SoBadItsGood>
--
-- Link example (series):
-- @[Elementary](\@tvtropes(series))@ →
-- <http://tvtropes.org/pmwiki/pmwiki.php/Series/Elementary>
--
-- You can give anything as a category instead of “series”, it'll be
-- capitalised but nothing else.
tvtropes :: Shortcut
tvtropes mbCat q = return $
format "http://tvtropes.org/pmwiki/pmwiki.php/{}/{}" cat q'
where
cat = maybe "Main" titleFirst mbCat
isSep c = (isSpace c || isPunctuation c) && c /= '\''
-- Break into words, transform each word like “it's” → “Its”, and concat.
-- Note that e.g. “man-made” is considered 2 separate words.
q' = T.concat $ map (titleFirst . T.filter isAlphaNum) (T.split isSep q)
ghcExtsList :: [(Text, Text)]
ghcExtsList = do
let (.=) = (,)
base = "https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/"
prefix x = map (\(a, b) -> (a, x <> b))
prefix base $ concat [
prefix "syntax-extns.html" [
"DisambiguateRecordFields" .= "#disambiguate-fields",
"EmptyCase" .= "#empty-case",
"NoImplicitPrelude" .= "#rebindable-syntax",
"NegativeLiterals" .= "#negative-literals",
"RebindableSyntax" .= "#rebindable-syntax",
"PatternGuards" .= "#pattern-guards",
"ViewPatterns" .= "#view-patterns",
"UnicodeSyntax" .= "#unicode-syntax",
"MagicHash" .= "#magic-hash",
"ParallelListComp" .= "#parallel-list-comprehensions",
"TransformListComp" .= "#generalised-list-comprehensions",
"MonadComprehensions" .= "#monad-comprehensions",
"ExplicitNamespaces" .= "#explicit-namespaces",
"RecursiveDo" .= "#recursive-do-notation",
"RecordWildCards" .= "#record-wildcards",
"NamedFieldPuns" .= "#record-puns",
"PackageImports" .= "#package-imports",
"LambdaCase" .= "#lambda-case",
"MultiWayIf" .= "#multi-way-if",
"NumDecimals" .= "#num-decimals",
"BinaryLiterals" .= "#binary-literals",
"PostfixOperators" .= "#postfix-operators",
"TupleSections" .= "#tuple-sections",
"PatternSynonyms" .= "#pattern-synonyms" ],
prefix "data-type-extensions.html" [
"GADTs" .= "#gadt",
"GADTSyntax" .= "#gadt-style",
"ExistentialQuantification" .= "#existential-quantification",
"LiberalTypeSynonyms" .= "#type-synonyms",
"EmptyDataDecls" .= "#nullary-types",
"DatatypeContexts" .= "#datatype-contexts",
"TypeOperators" .= "#type-operators" ],
prefix "other-type-extensions.html" [
"AllowAmbiguousTypes" .= "#ambiguity",
"ImplicitParams" .= "#implicit-parameters",
"NoMonomorphismRestriction" .= "#monomorphism",
"RelaxedPolyRec" .= "#typing-binds",
"MonoLocalBinds" .= "#mono-local-binds",
"ScopedTypeVariables" .= "#scoped-type-variables",
"ExplicitForAll" .= "#explicit-foralls",
"PolymorphicComponents" .= "#universal-quantification",
"Rank2Types" .= "#universal-quantification",
"RankNTypes" .= "#universal-quantification",
"ImpredicativeTypes" .= "#impredicative-polymorphism",
"KindSignatures" .= "#kinding",
"FlexibleContexts" .= "#flexible-contexts" ],
prefix "type-class-extensions.html" [
"IncoherentInstances" .= "#instance-overlap",
"OverlappingInstances" .= "#instance-overlap",
"OverloadedLists" .= "#overloaded-lists",
"OverloadedStrings" .= "#overloaded-strings",
"UndecidableInstances" .= "#undecidable-instances",
"TypeSynonymInstances" .= "#flexible-instance-head",
"FlexibleInstances" .= "#instance-rules",
"ConstrainedClassMethods" .= "#class-method-types",
"DefaultSignatures" .= "#class-default-signatures",
"MultiParamTypeClasses" .= "#multi-param-type-classes",
"NullaryTypeClasses" .= "#nullary-type-classes",
"InstanceSigs" .= "#instance-sigs",
"FunctionalDependencies" .= "#functional-dependencies" ],
prefix "deriving.html" [
"AutoDeriveTypeable" .= "#auto-derive-typeable",
"DeriveDataTypeable" .= "#deriving-typeable",
"DeriveGeneric" .= "#deriving-typeable",
"DeriveFunctor" .= "#deriving-extra",
"DeriveTraversable" .= "#deriving-extra",
"DeriveFoldable" .= "#deriving-extra",
"GeneralizedNewtypeDeriving" .= "#newtype-deriving",
"DeriveAnyClass" .= "#derive-any-class",
"StandaloneDeriving" .= "#stand-alone-deriving" ],
prefix "template-haskell.html" [
"TemplateHaskell" .= "",
"QuasiQuotes" .= "#th-quasiquotation" ],
prefix "ffi.html" [
"ForeignFunctionInterface" .= "",
"InterruptibleFFI" .= "#ffi-interruptible",
"CApiFFI" .= "#ffi-capi" ],
prefix "partial-type-signatures.html" [
"PartialTypeSignatures" .= "",
"NamedWildCards" .= "#named-wildcards" ],
map (.= "safe-haskell.html") [
"Safe",
"Trustworthy",
"Unsafe" ],
[ "Arrows" .= "arrow-notation.html",
"ConstraintKinds" .= "constraint-kind.html",
"DataKinds" .= "promotion.html",
"ExtendedDefaultRules" .= "interactive-evaluation.html#extended-default-rules",
"TypeFamilies" .= "type-families.html",
"PolyKinds" .= "kind-polymorphism.html",
"BangPatterns" .= "bang-patterns.html",
"CPP" .= "options-phases.html#c-pre-processor",
"RoleAnnotations" .= "roles.html#role-annotations",
"UnboxedTuples" .= "primitives.html#unboxed-tuples" ] ]