acme-lolcat (empty) → 0.1
raw patch · 6 files changed
+337/−0 lines, 6 filesdep +basedep +parsecdep +randomsetup-changed
Dependencies added: base, parsec, random, random-shuffle, text
Files
- Acme/LOLCAT.hs +244/−0
- Acme/LOLCAT/IO.hs +24/−0
- LICENSE +30/−0
- README.markdown +3/−0
- Setup.lhs +3/−0
- acme-lolcat.cabal +33/−0
+ Acme/LOLCAT.hs view
@@ -0,0 +1,244 @@+-- | Module: Acme.LOLCAT+-- Copyright: (c) 2013 Antonio Nikishaev+-- License: BSD+-- Maintainer: me@lelf.lu+--+--+-- LOLCAT translator.+--+-- Roughly based on <https://metacpan.org/pod/Acme::LOLCAT Acme::LOLCAT>+-- for Perl.++{-# LANGUAGE OverloadedStrings, FlexibleInstances, TupleSections #-}+{-# LANGUAGE Trustworthy #-}++module Acme.LOLCAT (translate, KindaText()) where++import Data.Text (Text)+import qualified Data.Text as T++import Text.Parsec+import Text.Parsec.Text()++import Control.Applicative ((<$>),(<*),(<*>))+import Control.Arrow+import Control.Monad+import Data.String (IsString(..))+import Data.Monoid+import Data.Char++import System.Random+import qualified System.Random.Shuffle as SHU (shuffle')++import Acme.LOLCAT.IO+++{-# NOINLINE shuffle #-}+shuffle :: [a] -> [a]+shuffle xs = do io <- OH HAI I CAN HAZ IO? THXBYE+ SHU.shuffle' xs (length xs) (io newStdGen)+++-- | Given a list, return a infinity list of its elements in random order+variants :: [a] -> [a]+variants xs = shuffle xs ++ variants xs++++type Parser = Parsec Text ParserState+data ParserState = Word | Punct deriving Eq++type Pattern = Parser String+++-- | Replace the part that matched by pattern PAT with TO in S.+-- Return Right NEW-STRING or Left ORIGINAL if nothing matches.+replaceOne :: Pattern -> Text -> Text -> Either Text Text+replaceOne pat to s | Right s' <- parsed = Right s'+ | otherwise = Left s+ where repl (pref,r) = pref <> to <> T.drop (T.length pref + length r) s+ parsed = repl <$> myRun (find pat) s+++-- | Run parser+myRun :: Parser a -> Text -> Either ParseError a+myRun p s = runP p Punct "" s+++-- | Replace PAT with TOS (cycling) in STR+replace :: Pattern -> [Text] -> Text -> Text+replace pat tos str = repl (cycle tos) $ Right str+ where repl (t:ts) (Right s) = repl ts $ replaceOne pat t s+ repl _ (Left s) = s+++{-# NOINLINE translateT #-}+translateT :: Text -> Text+translateT src+ | n == 1 = base <> " THX"+ | n == 2 = base <> " THXBYE."+ | otherwise = base+ where+ Just n = OH HAI I CAN HAZ IO? THXBYE+ <*> Just (randomRIO (1,10)) :: Maybe Int++ base = T.toUpper $ last $ scanl f src rules+ f s (pat,repls) = replace pat (variants repls) s+++++-- | Text/String-like things+class KindaText a where+ fromText :: Text -> a+ toText :: a -> Text++instance KindaText Text where+ fromText = id+ toText = id++instance KindaText String where+ fromText = T.unpack+ toText = T.pack+++-- | >>> translate "You too can speak like a lolcat!"+-- YOU 2 CAN SPEKK LIEK LOLCAT! THXBYE.+translate :: KindaText s => s -> s+translate = fromText . translateT . toText++++instance IsString (Parser String) where+ fromString = string+++-- | Given a parser for X returns a new parser for “smth and then X”+-- returning (SMTH,X)+-- +-- Weird? This is Acme.*.+find :: Pattern -> Parser (Text,String)+find pat = try (("",) <$> pat)+ <|> do c <- anyChar+ putState $ if isLetter c then Word else Punct+ first (T.cons c) <$> find pat+++-- | word S exactly+word :: String -> Parser String+word s = do Punct <- getState+ string s <* wordEnd++-- | S is inside word+inside :: String -> Parser String+inside s = do Word <- getState+ string s <* letter++-- | word S and then any punctuations+wordPuncts :: String -> Parser String+wordPuncts w = (++) <$> word w <*> many1 space++-- | word ending with S+wEnds :: String -> Parser String+wEnds s = string s <* wordEnd+++wordEnd = notFollowedBy letter+++++main = forever $ getLine >>= putStrLn . translate++++rules :: [(Parser String, [Text])]++rules = [+ ("what", ["wut", "whut"]),+ (wEnds "you", ["yu", "yous", "yoo", "u"]),+ ("cture", ["kshur"]),+ ("unless", ["unles"]),+ (wEnds "the", ["teh"]),+ ("more", ["moar"]),+ ("my", ["muh", "mah"]),+ ("are", ["r", "is", "ar"]),+ (word "a", [""]),+ ("eese", ["eez"]),+ ("catamorphi", ["cat-a-murrphi"]),+ ("morphi", ["murrphi"]),+ ("ph", ["f"]),+ (wEnds "as", ["az"]),+ ("seriously", ["srsly"]),+ (wEnds "er", ["r"]),+ ("sion", ["shun"]),+ ("just", ["jus"]),+ (wEnds "ose", ["oze"]),+ ("eady", ["eddy"]),+ (wEnds "om" <|> wEnds "ome", ["um"]),+ (wEnds "of", ["of", "ov", "of"]),+ ("uestion", ["wesjun"]),+ (word "want", ["wants"]),+ (wEnds "ead", ["edd"]),+ ("ucke", ["ukki", "ukke"]),+ ("sion", ["shun"]),+ ("eak", ["ekk"]),+ ("age", ["uj"]),+ ("like", ["likes", "liek"]),+ ("love", ["loves", "lub", "lubs", "luv"]),+ (word "is", ["ar teh","ar"]),+ (wEnds "nd", ["n"]),+ ("who", ["hoo"]),+ ("'", [""]),+ (wEnds "ese", ["eez"]),+ ("outh", ["owf"]),+ ("scio", ["shu"]),+ ("esque", ["esk"]),+ ("ture", ["chur"]),+ (word "too" <|> word "to", ["to", "t", "2", "to", "t"]),+ ("tious", ["shus"]),+ (wEnds "sure", ["shur"]),+ (wEnds "tty", ["tteh"]),+ ("were", ["was"]),+ (wEnds "ok", ["k", "kay"]),+ ("ym", ["im"]),+ (wEnds "thy", ["fee"]),+ (inside "ly", ["li"]),+ ("que" <* letter, ["kwe"]),+ ("oth", ["udd"]), -- ?+ ("ease", ["eez"]),+ (wEnds "ing", ["in", "ins", "ng", "ing"]),+ ("your", ["yur", "ur", "yore", "yoar"]),+ (wEnds "ove", ["oov", "ove", "uuv", "uv", "oove"]),+ ("for", ["for", "4", "fr", "fur", "for", "foar"]),+ ("thank", ["fank", "tank", "thx", "thnx"]),+ ("good", ["gud", "goed", "guud", "gude", "gewd"]),+ ("really", ["rly", "rily", "rilly", "rilley"]),+ ("world", ["wurrld", "whirld", "wurld", "wrld"]),+ (word "i'm" <|> word "im", ["im"]),++ -- ("(?!e)ight", ["ite"]),+ ("tion", ["shun"]), -- ("(?!ues)tion",["shun"])+ ("you're" <|> "youre" <|> "you are",+ ["yore", "yr"]),++-- ("\\boh\\b(?!.*hai)", ["o", "ohs"]),+ (word "oh", ["o", "ohs"]), -- ???++-- ("can" <+spaces, [""]),++ (join<$>sequence [wordPuncts "can",+ wordPuncts "i",+ wordPuncts "have",+ word "a"], ["i can has"]),++ ("have", ["has", "hav", "haz a"]),++ (word "hello" <|> word "hi"+ <|> word "hey" <|> word "howdy" <|> word "yo",+ ["oh hai"]),++ (word "god", ["ceiling cat"])++ ]+
+ Acme/LOLCAT/IO.hs view
@@ -0,0 +1,24 @@+-- | Module: Acme.LOLCAT+-- Copyright: (c) 2013 Antonio Nikishaev+-- License: BSD+-- Maintainer: me@lelf.lu+{-# LANGUAGE Unsafe #-}++module Acme.LOLCAT.IO (OH(..),HAI(..),I(..),CAN(..),HAZ(..),+ IO(..),YO(..),(?),THXBYE(..)) where++import Prelude hiding (IO)+import System.IO.Unsafe (unsafePerformIO)+++data HAI a b c d e = HAI a b c d e+data OH a b c d e = OH a b c d e+data I = I+data IO = IO+data YO = YO+data CAN = CAN+data HAZ = HAZ+data THXBYE = THXBYE++_?_ = return unsafePerformIO+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, Antonio Nikishaev++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Anton Nikishaev nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.markdown view
@@ -0,0 +1,3 @@+LOLCAT translator.++Roughly based on [Acme::LOLCAT](https://metacpan.org/pod/Acme::LOLCAT)
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ acme-lolcat.cabal view
@@ -0,0 +1,33 @@+name: acme-lolcat+version: 0.1+homepage: https://github.com/llelf/acme-lolcat+synopsis: LOLSPEAK translator+description: LOLSPEAK translator+license: BSD3+license-file: LICENSE+author: Antonio Nikishaev <me@lelf.lu>+maintainer: Antonio Nikishaev <me@lelf.lu>+copyright: 2013,2014 Antonio Nikishaev+category: Acme+build-type: Simple+cabal-version: >=1.14+extra-source-files: README.markdown+tested-with: GHC==7.6.3, GHC==7.8.3, GHC==7.9.20140419++library+ exposed-modules: Acme.LOLCAT, Acme.LOLCAT.IO+ build-depends: + base >= 4.5 && < 5, parsec >= 1.3.1, text >= 0.11.3.1,+ random >= 1.0.1.1, random-shuffle >= 0.0.4+ default-language: Haskell2010+-- ghc-options: -Wall++source-repository head+ type: git+ location: https://github.com/llelf/acme-lolcat++source-repository head+ type: darcs+ location: http://hub.darcs.net/lelf/acme-lolcat++