Skip to content

Commit

Permalink
Merge pull request #70 from gvolpe/feature/emoji-support
Browse files Browse the repository at this point in the history
feature: add emoji support
  • Loading branch information
gvolpe authored Oct 16, 2022
2 parents 701e926 + 8a33e7c commit 9e2e61c
Show file tree
Hide file tree
Showing 11 changed files with 94 additions and 44 deletions.
8 changes: 4 additions & 4 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dconf2nix (ProcessTimeout t) fa successMsg = timeout (t * 1000000) fa >>= \case

main :: IO ()
main = runArgs >>= \case
FileInput (FileArgs i o r t v) ->
dconf2nix t (dconf2nixFile i o r v) (Just "🚀 Successfully Nixified! ❄️")
StdinInput (StdinArgs r t v) ->
dconf2nix t (dconf2nixStdin r v) Nothing
FileInput (FileArgs i o r t e v) ->
dconf2nix t (dconf2nixFile i o r e v) (Just "🚀 Successfully Nixified! ❄️")
StdinInput (StdinArgs r t e v) ->
dconf2nix t (dconf2nixStdin r e v) Nothing
3 changes: 3 additions & 0 deletions data/emoji.settings
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[ org/gnome/Characters ]
recent-characters=['💡']
some-other-character=['🤓']
1 change: 1 addition & 0 deletions dconf2nix.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ library
other-modules: Paths_dconf2nix
build-depends: base
, containers
, emojis
, optparse-applicative
, parsec
, text
Expand Down
14 changes: 14 additions & 0 deletions output/emoji.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Generated via dconf2nix: https://github.com/gvolpe/dconf2nix
{ lib, ... }:

with lib.hm.gvariant;

{
dconf.settings = {
"org/gnome/Characters" = {
recent-characters = [ "💡" ];
some-other-character = [ "🤓" ];
};

};
}
9 changes: 8 additions & 1 deletion src/CommandLine.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ data FileArgs = FileArgs
, fileOutput :: OutputFilePath
, fileRoot :: Root
, fileTimeout :: ProcessTimeout
, fileEmojiSupport :: EmojiSupport
, fileVerbosity :: Verbosity
}

data StdinArgs = StdinArgs
{ stdinRoot :: Root
, stdinTimeout :: ProcessTimeout
, stdinEmojiSupport :: EmojiSupport
, stdinVerbosity :: Verbosity
}

Expand All @@ -38,6 +40,10 @@ verbosityArgs :: Parser Verbosity
verbosityArgs =
flag Normal Verbose (long "verbose" <> help "Verbose mode (debug)")

emojiArgs :: Parser EmojiSupport
emojiArgs =
flag Disabled Enabled (long "emoji" <> short 'e' <> help "Enable emoji support (adds a bit of overhead)")

rootArgs :: Parser Root
rootArgs = Root <$> strOption
(long "root" <> short 'r' <> value T.empty <> help
Expand All @@ -56,11 +62,12 @@ fileArgs = fmap FileInput $ FileArgs
)
<*> rootArgs
<*> timeoutArgs
<*> emojiArgs
<*> verbosityArgs

stdinArgs :: Parser Input
stdinArgs =
StdinInput <$> (StdinArgs <$> rootArgs <*> timeoutArgs <*> verbosityArgs)
StdinInput <$> (StdinArgs <$> rootArgs <*> timeoutArgs <*> emojiArgs <*> verbosityArgs)

versionInfo :: String
versionInfo = unlines
Expand Down
49 changes: 30 additions & 19 deletions src/DConf.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import qualified Data.Map as Map
import Data.Text ( Text )
import qualified Data.Text as T
import DConf.Data
import Text.Emoji ( emojis )
import Text.Parsec

type Parser
Expand Down Expand Up @@ -48,22 +49,30 @@ vInt64 = try $ do
many1 (string "int64 ") >> spaces
I64 . read <$> many1 digit

vTuple :: Parsec Text () Value
vTuple = try $ do
vTuple :: EmojiSupport -> Parsec Text () Value
vTuple es = try $ do
char '('
rs <- manyTill (dconf manyTill `sepBy` (string "," >> spaces)) (char ')')
rs <- manyTill (dconf es manyTill `sepBy` (string "," >> spaces)) (char ')')
case concat rs of
(x : y : _) -> pure $ T x y
_ -> fail "Not a tuple"

vTupleInList :: Parsec Text () Value
vTupleInList = vTuple <&> \case
vTupleInList :: EmojiSupport -> Parsec Text () Value
vTupleInList es = vTuple es <&> \case
T x y -> TL x y
a -> a

vEmptyString :: Parsec Text () Value
vEmptyString = S "" <$ (try (string "''") <|> try (string "\"\""))

vEmoji :: Parsec Text () Value
vEmoji =
let e = T.head . snd <$> emojis
f = choice $ char <$> e
s = many1 (string "'") *> f <* (string "'")
d = many1 (char '"') *> f <* (char '"')
in Emo <$> try (s <|> d)

vString :: Parser -> Parsec Text () Value
vString parser = try $ do
S . T.pack . concat <$> (single <|> double)
Expand All @@ -78,9 +87,11 @@ vString parser = try $ do
vAny :: Parsec Text () Value
vAny = S . T.pack <$> manyTill anyChar (try $ lookAhead endOfLine)

dconf :: Parser -> Parsec Text () Value
dconf p = choice
[vBool, vInt, vDouble, vUint32, vInt64, vEmptyString, vString p, vTuple, vAny]
dconf :: EmojiSupport -> Parser -> Parsec Text () Value
dconf Enabled p = choice
[vBool, vInt, vDouble, vUint32, vInt64, vEmptyString, vEmoji, vString p, vTuple Enabled, vAny]
dconf Disabled p = choice
[vBool, vInt, vDouble, vUint32, vInt64, vEmptyString, vString p, vTuple Disabled, vAny]

-- There is no support for variants in HM yet so we parse them as a string
vListOfVariant :: Parsec Text () Value
Expand All @@ -94,11 +105,11 @@ vListOfVariant =
manyTill anyToken (try $ lookAhead $ string "\"") <* char '"'
in S . T.pack <$> (variant1 <|> variant2)

vList :: Parsec Text () Value
vList = try $ do
vList :: EmojiSupport -> Parsec Text () Value
vList es = try $ do
char '['
L . concat <$> manyTill
((vTupleInList <|> vJson <|> dconf manyTill) `sepBy` (string "," >> spaces))
((vTupleInList es <|> vJson <|> dconf es manyTill) `sepBy` (string "," >> spaces))
(char ']')

vJson :: Parsec Text () Value
Expand All @@ -117,19 +128,19 @@ dconfHeader = do
T.pack . concat <$> manyTill tokens (string " ]" <|> string "]")
where tokens = choice $ many1 <$> [oneOf "/.-:_", alphaNum]

dconfValue :: Parsec Text () Value
dconfValue = vListOfVariant <|> vList <|> vEmptyList <|> vJson <|> dconf endBy
dconfValue :: EmojiSupport -> Parsec Text () Value
dconfValue es = vListOfVariant <|> vList es <|> vEmptyList <|> vJson <|> dconf es endBy

vKey :: Parsec Text () Key
vKey = Key . T.pack <$> manyTill (choice [alphaNum, char '-']) (char '=')

entryParser :: Parsec Text () Entry
entryParser = do
entryParser :: EmojiSupport -> Parsec Text () Entry
entryParser es = do
h <- dconfHeader <* endOfLine
kv <- many1 ((,) <$> vKey <*> (dconfValue <* endOfLine))
kv <- many1 ((,) <$> vKey <*> (dconfValue es <* endOfLine))
optional endOfLine
pure $ Entry h (Map.fromList kv)

dconfParser :: Verbosity -> Parsec Text () [Entry]
dconfParser Normal = manyTill entryParser eof
dconfParser Verbose = parserTraced "dconf" $ dconfParser Normal
dconfParser :: EmojiSupport -> Verbosity -> Parsec Text () [Entry]
dconfParser es Normal = manyTill (entryParser es) eof
dconfParser es Verbose = parserTraced "dconf" $ dconfParser es Normal
2 changes: 2 additions & 0 deletions src/DConf/Data.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ newtype InputFilePath = InputFilePath FilePath deriving Show
newtype OutputFilePath = OutputFilePath FilePath deriving Show
newtype ProcessTimeout = ProcessTimeout Int deriving Show

data EmojiSupport = Enabled | Disabled
data Verbosity = Normal | Verbose

newtype Nix = Nix { unNix :: Text } deriving Show
Expand All @@ -21,6 +22,7 @@ data Value = S Text -- String
| I32 Int -- Int32
| I64 Int -- Int64
| D Double -- Double
| Emo Char -- Emoji (Unicode char)
| T Value Value -- Tuple
| TL Value Value -- Tuple within a list
| L [Value] -- List of values
Expand Down
12 changes: 6 additions & 6 deletions src/DConf2Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ import Text.Parsec ( ParseError
, runParser
)

dconf2nixFile :: InputFilePath -> OutputFilePath -> Root -> Verbosity -> IO ()
dconf2nixFile (InputFilePath input) (OutputFilePath output) root v =
dconf2nixFile :: InputFilePath -> OutputFilePath -> Root -> EmojiSupport -> Verbosity -> IO ()
dconf2nixFile (InputFilePath input) (OutputFilePath output) root es v =
let run = handler (T.writeFile output) (T.appendFile output) root
parse = parseFromFile (dconfParser v) input
parse = parseFromFile (dconfParser es v) input
in run =<< parse

dconf2nixStdin :: Root -> Verbosity -> IO ()
dconf2nixStdin root v =
dconf2nixStdin :: Root -> EmojiSupport -> Verbosity -> IO ()
dconf2nixStdin root es v =
let run = handler T.putStr T.putStr root
parse = runParser (dconfParser v) () "<stdin>"
parse = runParser (dconfParser es v) () "<stdin>"
in run . parse =<< T.getContents

handler
Expand Down
1 change: 1 addition & 0 deletions src/Nix.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ renderValue raw = Nix $ renderValue' raw <> ";"
renderValue' (B v) = T.toLower . T.pack $ show v
renderValue' (I v) = T.pack $ show v
renderValue' (D v) = T.pack $ show v
renderValue' (Emo v) = "\"" <> T.singleton v <> "\""
renderValue' (I32 v) = "mkUint32 " <> T.pack (show v)
renderValue' (I64 v) = "mkInt64 " <> T.pack (show v)
renderValue' (T x y) =
Expand Down
37 changes: 24 additions & 13 deletions test/DConf2NixTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,24 @@ import Text.Parsec ( runParser )
prop_dconf2nix :: Property
prop_dconf2nix = withTests (10 :: TestLimit) dconf2nix

baseProperty :: FilePath -> FilePath -> Root -> Property
baseProperty i o root = property $ do
baseProperty :: FilePath -> FilePath -> Root -> EmojiSupport -> Property
baseProperty i o root es = property $ do
input <- evalIO $ T.readFile i
output <- evalIO $ T.readFile o
ref <- evalIO $ newIORef T.empty
evalIO $ handler (writer ref) (writer ref) root (entries input)
result <- evalIO $ readIORef ref
result === output
where
entries = runParser (dconfParser Normal) () "<test>"
entries = runParser (dconfParser es Normal) () "<test>"
writer ref x = modifyIORef ref (`T.append` x)

dconf2nix :: Property
dconf2nix =
let input = "data/dconf.settings"
output = "output/dconf.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_custom_root :: Property
prop_dconf2nix_custom_root = withTests (10 :: TestLimit) dconf2nixCustomRoot
Expand All @@ -44,7 +44,7 @@ dconf2nixCustomRoot =
let input = "data/custom.settings"
output = "output/custom.nix"
root = Root "ca/desrt/dconf-editor"
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_custom_nested_root :: Property
prop_dconf2nix_custom_nested_root =
Expand All @@ -55,14 +55,14 @@ dconf2nixCustomNestedRoot =
let input = "data/nested.settings"
output = "output/nested.nix"
root = Root "org/gnome/desktop/peripherals"
in baseProperty input output root
in baseProperty input output root Disabled

dconf2nixIndexer :: Property
dconf2nixIndexer =
let input = "data/indexer.settings"
output = "output/indexer.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_indexer :: Property
prop_dconf2nix_indexer = withTests (10 :: TestLimit) dconf2nixIndexer
Expand All @@ -72,7 +72,7 @@ dconf2nixNegative =
let input = "data/negative.settings"
output = "output/negative.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_negative :: Property
prop_dconf2nix_negative = withTests (10 :: TestLimit) dconf2nixNegative
Expand All @@ -82,7 +82,7 @@ dconf2nixJson =
let input = "data/json.settings"
output = "output/json.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_json :: Property
prop_dconf2nix_json = withTests (10 :: TestLimit) dconf2nixJson
Expand All @@ -92,7 +92,7 @@ dconf2nixClocks =
let input = "data/clocks.settings"
output = "output/clocks.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_clocks :: Property
prop_dconf2nix_clocks = withTests (10 :: TestLimit) dconf2nixClocks
Expand All @@ -102,7 +102,7 @@ dconf2nixKeybindings =
let input = "data/keybindings.settings"
output = "output/keybindings.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_keybindings :: Property
prop_dconf2nix_keybindings = withTests (10 :: TestLimit) dconf2nixKeybindings
Expand All @@ -112,7 +112,7 @@ dconf2nixScientificNotation =
let input = "data/scientific-notation.settings"
output = "output/scientific-notation.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_scientific_notation :: Property
prop_dconf2nix_scientific_notation =
Expand All @@ -123,11 +123,22 @@ dconf2nixHeaders =
let input = "data/headers.settings"
output = "output/headers.nix"
root = Root T.empty
in baseProperty input output root
in baseProperty input output root Disabled

prop_dconf2nix_headers :: Property
prop_dconf2nix_headers =
withTests (10 :: TestLimit) dconf2nixHeaders

dconf2nixEmoji :: Property
dconf2nixEmoji =
let input = "data/emoji.settings"
output = "output/emoji.nix"
root = Root T.empty
in baseProperty input output root Enabled

prop_dconf2nix_emoji :: Property
prop_dconf2nix_emoji =
withTests (10 :: TestLimit) dconf2nixEmoji

dconf2nixTests :: Group
dconf2nixTests = $$(discover)
2 changes: 1 addition & 1 deletion test/DConfTest.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ prop_simple_parser = withTests (100 :: TestLimit) simpleParser

simpleParser :: Property
simpleParser =
let entries = runParser (dconfParser Normal) () "<test>" testInput
let entries = runParser (dconfParser Disabled Normal) () "<test>" testInput
in property $ entries === Right [testOutput]

testInput :: Text
Expand Down

0 comments on commit 9e2e61c

Please sign in to comment.