Commit 54ce3e1a authored by Nicolas Lenz's avatar Nicolas Lenz

Merge branch 'master' of git.eisfunke.com:software/Mock

parents ed0df34c af0b4216
# ---> Haskell
mock.cabal
dist
dist-*
cabal-dev
......@@ -19,4 +20,3 @@ cabal.sandbox.config
.stack-work/
cabal.project.local
.HTF/
......@@ -2,40 +2,43 @@
![wAR miR jEtzT Zu anSTRENgEnd dA JedeN ZWEiten BUChSTaBeN GRoSS zU scHREiBen](mock.png)
There is a **Telegram bot** for Mock available as [\@truemockbot](https://t.me/truemockbot), you can find its source code in the [repository](https://git.eisfunke.com/software/mock-telegram-bot).
## Installation
Just clone this repository or download a [release](https://git.eisfunke.com/software/mock/releases) and call
```
$> stack setup
$> stack install
$ stack install
```
This will install Mock into `~/.local/bin`, which should be added to `$PATH`.
inside the folder. This will install Mock into `~/.local/bin`, which should be added to `$PATH`.
There is also an [AUR package](https://aur.archlinux.org/packages/haskell-mock/) available.
If you're using Arch Linux: there is also an [AUR package](https://aur.archlinux.org/packages/haskell-mock/) available.
## Usage
`mock [STYLE] [TEXT]`
You can get a list of possible mock styles with `mock`.
You can get help a list of possible mock styles with `mock`.
If no text is given, input is read from `stdin`.
If no text or "-" is given, input is read from `stdin`.
### Examples
```
$> mock random This is a great program.
$ mock random This is a great program.
ThIs Is A greaT PROgrAM.
$> mock space This is a great program.
$ mock space This is a great program.
T h i s i s a g r e a t p r o g r a m.
```
Mock calls can be concatenated with pipes:
Mock calls can of course be concatenated with pipes:
```
$> mock space This is a great program. | mock random
$ mock space This is a great program. | mock random
T h I S i S A G R e A t P R o g r a m .
```
......
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Mock (styles)
import Mock.Help (styleHelp)
import Text.Mock
import Text.Mock.Help
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Char
import Data.Maybe
import System.Environment
-- |Main function.
main :: IO ()
main = do
......@@ -22,6 +19,9 @@ main = do
[style] -> do
input <- T.getContents -- Read from stdin
T.putStrLn $ handle style [input]
[style, "-"] -> do
input <- T.getContents -- Read from stdin
T.putStrLn $ handle style [input]
(style:str) -> T.putStrLn $ handle style str
-- |Returns an IO action handling the given list of arguments.
......@@ -32,7 +32,7 @@ handle style = fromMaybe (const help) (lookup style styles) . T.dropWhileEnd isS
help :: T.Text
help = T.unlines [
" ╔════════════════════╗",
" ║ Mock 3.3.0 ║",
" ║ Mock " <> version <> " ║",
" ╚════════════════════╝",
"",
"A Great PrOgrAM tO TRANsFoRM TEXt, wRiTten iN HaSKeLL.",
......
cabal-version: 2.2
-- This file has been generated from package.yaml by hpack version 0.31.1.
--
-- see: https://github.com/sol/hpack
--
-- hash: 25216876ead15fc7d80c86db52d327284f1e1e11704a736cec1d15280cc22ed3
name: mock
version: 3.3.0
synopsis: GrEAt HAskeLL PrOGRaM to trANsForm tEXT
description: Please see the README at <https://git.eisfunke.com/software/mock#readme>
category: String
author: Nicolas Lenz
maintainer: nicolas@eisfunke.com
copyright: 2018 Nicolas Lenz
license: WTFPL
license-file: LICENSE
build-type: Simple
extra-source-files:
README.md
source-repository head
type: git
location: https://git.eisfunke.com/software/mock
library
exposed-modules:
Mock
Mock.Help
other-modules:
Paths_mock
hs-source-dirs:
src
build-depends:
base >=4.7 && <5
, hashable
, random
, text
default-language: Haskell2010
executable mock
main-is: Main.hs
other-modules:
Paths_mock
hs-source-dirs:
app
ghc-options: -threaded -rtsopts -with-rtsopts=-N
build-depends:
base >=4.7 && <5
, hashable
, mock
, random
, text
default-language: Haskell2010
name: mock
version: 3.4.0
license: WTFPL
git: "https://git.eisfunke.com/software/mock"
author: "Nicolas Lenz"
maintainer: "nicolas@eisfunke.com"
copyright: "2018 Nicolas Lenz"
name: mock
version: 3.6.0
license: WTFPL
git: https://git.eisfunke.com/software/mock
author: Nicolas Lenz
maintainer: nicolas@eisfunke.com
copyright: 2018-2019 Nicolas Lenz
extra-source-files:
- README.md
synopsis: GrEAt HAskeLL PrOGRaM to trANsForm tEXT
category: String
description: Please see the README at <https://git.eisfunke.com/software/mock#readme>
synopsis: GrEAt HAskeLL PrOGRaM to trANsForm tEXT
category: Text
description: Please see the README at <https://git.eisfunke.com/software/mock#readme>.
dependencies:
- base >= 4.7 && < 5
- random
- hashable
- text
- base
- text
- random
- hashable
extra-doc-files:
- README.md
library:
source-dirs: src
ghc-options:
- -Wall
executables:
mock:
main: Main.hs
source-dirs: app
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
source-dirs: app
main: main.hs
dependencies:
- mock
- mock
ghc-options:
- -Wall
- -threaded
- -rtsopts
- -with-rtsopts=-N
{-# LANGUAGE OverloadedStrings, LambdaCase #-}
module Text.Mock (styles, version) where
import Data.Text (Text)
import qualified Data.Text as T
import Data.Char
import Data.List
import Data.Hashable
import System.Random
-- |Version string
version :: Text
version = "3.6.0"
-- | List of all mock styles as tuples of the name and the transformation function.
styles :: [(Text, Text -> Text)]
styles = [
("random", mockRandom),
("alternate", mockAlternate),
("alternate2", mockAlternate . T.toLower),
("strike", strikethrough),
("double", T.map toDouble),
("dedouble", T.map fromDouble),
("smallcaps", T.map toSmallCap),
("lower", T.toLower),
("upper", T.toUpper),
("cyrillic", T.map toCyrillic),
("subsuper", mockSubSuper),
("cc", mockCC),
("b", mockB),
("pray", T.unwords . intersperse "🙏" . T.words),
("clap", T.unwords . intersperse "👏" . T.words),
("space", letterspace 1),
("space2", letterspace 2),
("space3", letterspace 3),
("lines", T.intersperse '\n'),
("wordlines", T.concat . intersperse "\n" . T.words),
("square", mockSquare)]
-- | Transforms characters of a string into uppercase where the corresponding element of the bool list is true. On encountering a letter that already is uppercase the mask is reversed.
toUpperBy :: [Bool] -> Text -> Text
toUpperBy mask' = fst . T.foldl f ("", mask') where
f :: (Text, [Bool]) -> Char -> (Text, [Bool])
f (txt, bit:mask) char
| isUpper char = (txt `T.snoc` char, map not mask)
| isSpace char = (txt `T.snoc` char, bit:mask)
f (txt, True:mask) char = (txt `T.snoc` toUpper char, mask)
f (txt, False:mask) char = (txt `T.snoc` char, mask)
f (txt, []) char = (txt `T.snoc` char, []) -- If the mask is empty, treat is as all false
-- | Transforms every other of the characters of a string into uppercase. The other characters aren't changed.
mockAlternate :: Text -> Text
mockAlternate = toUpperBy (intersperse True $ repeat False)
-- | Tansforms random (that is, pseudo-random per input) characters of a string into uppercase.
mockRandom :: Text -> Text
mockRandom txt = toUpperBy (randoms $ mkStdGen (hash txt)) txt
-- | Letterspaces a String with the given number of blanks between each character.
letterspace :: Int -> Text -> Text
letterspace n = T.pack . intercalate (replicate n ' ') . map (:[]) . T.unpack
-- | Transforms characters into their double-struck variant if available.
toDouble :: Char -> Char
toDouble 'C' = chr 8450
toDouble 'H' = chr 8461
toDouble 'N' = chr 8469
toDouble 'P' = chr 8473
toDouble 'Q' = chr 8474
toDouble 'R' = chr 8477
toDouble 'Z' = chr 8484
toDouble c
| 48 <= ord c && ord c <= 57 = chr $ ord c - 48 + 120792 -- Number
| 65 <= ord c && ord c <= 90 = chr $ ord c - 65 + 120120 -- Uppercase letter
| 97 <= ord c && ord c <= 122 = chr $ ord c - 97 + 120146 -- Lowercase letter
toDouble c = c
-- | Transforms double-struck characters back into their normal variant.
fromDouble :: Char -> Char
fromDouble c = case ord c of
8450 -> 'C'
8461 -> 'H'
8469 -> 'N'
8473 -> 'P'
8474 -> 'Q'
8477 -> 'R'
8484 -> 'Z'
code
| 120792 <= code && code <= 120801 -> chr $ code - 120792 + 48
| 120120 <= code && code <= 120145 -> chr $ code - 120120 + 65
| 120146 <= code && code <= 120171 -> chr $ code - 120146 + 97
code -> chr code
-- | Transforms characters into sub- and superscript alternatingly.
mockSubSuper :: Text -> Text
mockSubSuper txt = T.pack $ zipWith toSubSuper (intersperse True $ repeat False) (T.unpack txt)
-- | Transforms a character into a unicode sub- or superscript variant. If true is given and a subscript version is available, that is used. If none is available or false is given, a superscript version is used. If none is available, the character is left unchanged.
toSubSuper :: Bool -> Char -> Char
toSubSuper = curry $ \case
(_, 'A') -> chr 7468
(_, 'B') -> chr 7470
(_, 'D') -> chr 7472
(_, 'E') -> chr 7473
(_, 'G') -> chr 7475
(_, 'H') -> chr 7476
(_, 'I') -> chr 7477
(_, 'J') -> chr 7478
(_, 'K') -> chr 7479
(_, 'L') -> chr 7480
(_, 'M') -> chr 7481
(_, 'N') -> chr 7482
(_, 'O') -> chr 7484
(_, 'P') -> chr 7486
(_, 'R') -> chr 7487
(_, 'T') -> chr 7488
(_, 'U') -> chr 7489
(_, 'V') -> chr 11389
(_, 'W') -> chr 7490
(False, 'a') -> 'ᵃ'
(True, 'a') -> 'ₐ'
(_, 'b') -> 'ᵇ'
(_, 'c') -> 'ᶜ'
(_, 'd') -> 'ᵈ'
(False, 'e') -> 'ᵉ'
(True, 'e') -> 'ₑ'
(_, 'f') -> 'ᶠ'
(_, 'g') -> 'ᵍ'
(False, 'h') -> 'ʰ'
(True, 'h') -> 'ₕ'
(False, 'i') -> 'ⁱ'
(True, 'i') -> 'ᵢ'
(False, 'j') -> 'ʲ'
(True, 'j') -> 'ⱼ'
(False, 'k') -> 'ᵏ'
(True, 'k') -> 'ₖ'
(False, 'l') -> 'ˡ'
(True, 'l') -> 'ₗ'
(False, 'm') -> 'ᵐ'
(True, 'm') -> 'ₘ'
(False, 'n') -> 'ⁿ'
(True, 'n') -> 'ₙ'
(False, 'o') -> 'ᵒ'
(True, 'o') -> 'ₒ'
(False, 'p') -> 'ᵖ'
(True, 'p') -> 'ₚ'
(False, 'r') -> 'ʳ'
(True, 'r') -> 'ᵣ'
(False, 's') -> 'ˢ'
(True, 's') -> 'ₛ'
(False, 't') -> 'ᵗ'
(True, 't') -> 'ₜ'
(False, 'u') -> 'ᵘ'
(True, 'u') -> 'ᵤ'
(False, 'v') -> 'ᵛ'
(True, 'v') -> 'ᵥ'
(_, 'w') -> 'ʷ'
(False, 'x') -> 'ˣ'
(True, 'x') -> 'ₓ'
(_, 'y') -> 'ʸ'
(_, 'z') -> 'ᶻ'
(_, c) -> c
-- | Transforms lowercase characters into their unicode small capital variants.
toSmallCap :: Char -> Char
toSmallCap = \case
'a' -> chr 7424
'b' -> chr 665
'c' -> chr 7428
'd' -> chr 7429
'e' -> chr 7431
'f' -> chr 42800
'g' -> chr 610
'h' -> chr 668
'i' -> chr 618
'j' -> chr 7434
'k' -> chr 7435
'l' -> chr 671
'm' -> chr 7437
'n' -> chr 628
'o' -> chr 7439
'p' -> chr 7448
'q' -> chr 491
'r' -> chr 640
's' -> chr 42801
't' -> chr 7451
'u' -> chr 7452
'v' -> chr 7456
'w' -> chr 7457
'y' -> chr 655
'z' -> chr 7458
c -> c
-- | Replaces some characters with cyrillic ones *looking* similarly.
toCyrillic :: Char -> Char
toCyrillic = \case
'A' -> 'Д'
'B' -> 'Б'
'E' -> 'З'
'N' -> 'И'
'O' -> 'Ө'
'R' -> 'Я'
'U' -> 'Ц'
'W' -> 'Щ'
'X' -> 'Ж'
'a' -> 'д'
'b' -> 'в'
'e' -> 'ё'
'h' -> 'Ђ'
'i' -> 'ɪ'
'k' -> 'к'
'o' -> 'ө'
'r' -> 'я'
't' -> 'т'
'u' -> 'ц'
'y' -> 'џ'
c -> c
-- | Replaces all occurences of *lowercase* "g", "ck" and "k" in a string with "cc".
mockCC :: Text -> Text
mockCC = T.replace "k" "cc" . T.replace "ck" "cc"
-- | Replaces all occurences of "b", "B", "p" and "P" with B button emojis.
mockB :: Text -> Text
mockB = T.replace "b" "🅱️" . T.replace "B" "🅱️"
-- | Makes a square of a string by putting it with spaces in the first line and then all characters except the first in single lines after that first line.
mockSquare :: Text -> Text
mockSquare text = T.concat [T.intersperse ' ' text, "\n", T.intercalate "\n" (T.chunksOf 1 $ T.tail text)]
-- | Uses unicode U+0336 to let a text look struck through.
strikethrough :: Text -> Text
strikethrough text
| text == T.empty = T.empty
| otherwise = T.intersperse '\822' text `T.append` "\822"
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE OverloadedStrings, LambdaCase #-}
module Mock.Help (styleHelp) where
module Text.Mock.Help (styleHelp) where
import qualified Data.Text as T
import Data.Text (Text)
-- |Returns help string for a given style name (or a fitting message if no help is available).
styleHelp :: Text -> Text
styleHelp styleName = case styleName of
styleHelp = \case
"random" -> "Flips lowercase characters pseudo-randomly into uppercase letters."
"alternate" -> "Flips every second letter into an uppercase one, starting with the second character."
"space" -> "Inserts a s p a c e between every two characters."
"space2" -> "Inserts two s p a c e s between every two characters."
"space3" -> "Inserts three s p a c e s between every two characters."
"lines" -> "Puts each character on a single line."
"upper" -> "Turns all characters into UPPERCASE ones."
"lower" -> "Turns all characters into lowercase ones."
"alternate2" -> "Like alternate, but ignores case in the input. Equivalent to lower|alternate."
"strike" -> "Turns the input into strikethrough using Unicode combinators (e̶x̶a̶m̶p̶l̶e̶)."
"double" -> "Turns characters (latin letters and numbers) into their double-struck variants (𝕖𝕩𝕒𝕞𝕡𝕝𝕖). Also known as blackboard bold."
"dedouble" -> "Turns double-struck characters (like from the \"double\" style) back into normal ones."
"smallcaps" -> "Turns lowercase letters into small capitals."
"lower" -> "Turns all characters into lowercase ones."
"upper" -> "Turns all characters into UPPERCASE ones."
"cyrillic" -> "Turns the text into a stereotypical fake russian looking variant."
"subsuper" -> "Alternatingly put letters into sub- and superscript, where possible."
"cc" -> "Replaces all occurences of lowercase \"c\", \"ck\" and \"k\" with \"cc\"."
"b" -> "Replaces all occurences of Bs (lower- and uppercase) with B-button emojis (🅱)."
"pray" -> "Puts pray emojis (🙏) between all words."
"clap" -> "Puts clap emojis (👏) between all words."
"space" -> "Inserts a s p a c e between every two characters."
"space2" -> "Inserts two s p a c e s between every two characters."
"space3" -> "Inserts three s p a c e s between every two characters."
"lines" -> "Puts each character on a single line."
"wordlines" -> "Puts each word on a single line."
"square" -> "Shows the input spaced in the first line and the tail of the input lined afterwards."
"strike" -> "Turns the input into strikethrough using Unicode combinators (e̶x̶a̶m̶p̶l̶e̶)."
_ -> "No documentation available."
resolver: lts-12.24
resolver: lts-13.26
packages:
- .
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment