forked from GitHub/gf-core
added mode 'gf --run' for running silently a script ; made quizzes handle character encoding correctly ; for this end, collected coding functions in GF.Text.Coding
This commit is contained in:
@@ -37,5 +37,6 @@ mainOpts opts files =
|
|||||||
ModeVersion -> putStrLn $ "Grammatical Framework (GF) version " ++ showVersion version
|
ModeVersion -> putStrLn $ "Grammatical Framework (GF) version " ++ showVersion version
|
||||||
ModeHelp -> putStrLn helpMessage
|
ModeHelp -> putStrLn helpMessage
|
||||||
ModeInteractive -> mainGFI opts files
|
ModeInteractive -> mainGFI opts files
|
||||||
|
ModeRun -> mainRunGFI opts files
|
||||||
ModeCompiler -> dieIOE (mainGFC opts files)
|
ModeCompiler -> dieIOE (mainGFC opts files)
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import GF.Text.Lexing
|
|||||||
import GF.Text.Transliterations
|
import GF.Text.Transliterations
|
||||||
|
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
|
import GF.Text.Coding
|
||||||
|
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
@@ -63,10 +64,10 @@ emptyCommandInfo = CommandInfo {
|
|||||||
lookCommand :: String -> Map.Map String CommandInfo -> Maybe CommandInfo
|
lookCommand :: String -> Map.Map String CommandInfo -> Maybe CommandInfo
|
||||||
lookCommand = Map.lookup
|
lookCommand = Map.lookup
|
||||||
|
|
||||||
commandHelpAll :: (String -> String) -> PGF -> [Option] -> String
|
commandHelpAll :: String -> PGF -> [Option] -> String
|
||||||
commandHelpAll enc pgf opts = unlines
|
commandHelpAll cod pgf opts = unlines
|
||||||
[commandHelp (isOpt "full" opts) (co,info)
|
[commandHelp (isOpt "full" opts) (co,info)
|
||||||
| (co,info) <- Map.assocs (allCommands enc pgf)]
|
| (co,info) <- Map.assocs (allCommands cod pgf)]
|
||||||
|
|
||||||
commandHelp :: Bool -> (String,CommandInfo) -> String
|
commandHelp :: Bool -> (String,CommandInfo) -> String
|
||||||
commandHelp full (co,info) = unlines $ [
|
commandHelp full (co,info) = unlines $ [
|
||||||
@@ -82,8 +83,8 @@ commandHelp full (co,info) = unlines $ [
|
|||||||
] else []
|
] else []
|
||||||
|
|
||||||
-- this list must no more be kept sorted by the command name
|
-- this list must no more be kept sorted by the command name
|
||||||
allCommands :: (String -> String) -> PGF -> Map.Map String CommandInfo
|
allCommands :: String -> PGF -> Map.Map String CommandInfo
|
||||||
allCommands enc pgf = Map.fromList [
|
allCommands cod pgf = Map.fromList [
|
||||||
("cc", emptyCommandInfo {
|
("cc", emptyCommandInfo {
|
||||||
longname = "compute_concrete",
|
longname = "compute_concrete",
|
||||||
syntax = "cc (-all | -table | -unqual)? TERM",
|
syntax = "cc (-all | -table | -unqual)? TERM",
|
||||||
@@ -206,10 +207,10 @@ allCommands enc pgf = Map.fromList [
|
|||||||
_ | isOpt "coding" opts -> codingMsg
|
_ | isOpt "coding" opts -> codingMsg
|
||||||
_ | isOpt "license" opts -> licenseMsg
|
_ | isOpt "license" opts -> licenseMsg
|
||||||
[t] -> let co = getCommandOp (showTree t) in
|
[t] -> let co = getCommandOp (showTree t) in
|
||||||
case lookCommand co (allCommands enc pgf) of ---- new map ??!!
|
case lookCommand co (allCommands cod pgf) of ---- new map ??!!
|
||||||
Just info -> commandHelp True (co,info)
|
Just info -> commandHelp True (co,info)
|
||||||
_ -> "command not found"
|
_ -> "command not found"
|
||||||
_ -> commandHelpAll enc pgf opts
|
_ -> commandHelpAll cod pgf opts
|
||||||
in return (fromString msg)
|
in return (fromString msg)
|
||||||
}),
|
}),
|
||||||
("i", emptyCommandInfo {
|
("i", emptyCommandInfo {
|
||||||
@@ -253,6 +254,7 @@ allCommands enc pgf = Map.fromList [
|
|||||||
exec = \opts -> return . fromStrings . map (optLin opts),
|
exec = \opts -> return . fromStrings . map (optLin opts),
|
||||||
options = [
|
options = [
|
||||||
("all","show all forms and variants"),
|
("all","show all forms and variants"),
|
||||||
|
("multi","linearize to all languages (default)"),
|
||||||
("record","show source-code-like record"),
|
("record","show source-code-like record"),
|
||||||
("table","show all forms labelled by parameters"),
|
("table","show all forms labelled by parameters"),
|
||||||
("term", "show PGF term"),
|
("term", "show PGF term"),
|
||||||
@@ -282,7 +284,7 @@ allCommands enc pgf = Map.fromList [
|
|||||||
exec = \opts _ -> do
|
exec = \opts _ -> do
|
||||||
let lang = optLang opts
|
let lang = optLang opts
|
||||||
let cat = optCat opts
|
let cat = optCat opts
|
||||||
morphologyQuiz pgf lang cat
|
morphologyQuiz cod pgf lang cat
|
||||||
return void,
|
return void,
|
||||||
flags = [
|
flags = [
|
||||||
("lang","language of the quiz"),
|
("lang","language of the quiz"),
|
||||||
@@ -402,7 +404,7 @@ allCommands enc pgf = Map.fromList [
|
|||||||
let from = valIdOpts "from" (optLang opts) opts
|
let from = valIdOpts "from" (optLang opts) opts
|
||||||
let to = valIdOpts "to" (optLang opts) opts
|
let to = valIdOpts "to" (optLang opts) opts
|
||||||
let cat = optCat opts
|
let cat = optCat opts
|
||||||
translationQuiz pgf from to cat
|
translationQuiz cod pgf from to cat
|
||||||
return void,
|
return void,
|
||||||
flags = [
|
flags = [
|
||||||
("from","translate from this language"),
|
("from","translate from this language"),
|
||||||
@@ -507,6 +509,7 @@ allCommands enc pgf = Map.fromList [
|
|||||||
})
|
})
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
|
enc = encodeUnicode cod
|
||||||
lin opts t = unlines [linearize pgf lang t | lang <- optLangs opts]
|
lin opts t = unlines [linearize pgf lang t | lang <- optLangs opts]
|
||||||
par opts s = concat [parse pgf lang (optCat opts) s | lang <- optLangs opts]
|
par opts s = concat [parse pgf lang (optCat opts) s | lang <- optLangs opts]
|
||||||
|
|
||||||
@@ -616,15 +619,15 @@ stringOpOptions = [
|
|||||||
("words","lexer that assumes tokens separated by spaces (default)")
|
("words","lexer that assumes tokens separated by spaces (default)")
|
||||||
]
|
]
|
||||||
|
|
||||||
translationQuiz :: PGF -> Language -> Language -> Category -> IO ()
|
translationQuiz :: String -> PGF -> Language -> Language -> Category -> IO ()
|
||||||
translationQuiz pgf ig og cat = do
|
translationQuiz cod pgf ig og cat = do
|
||||||
tts <- translationList pgf ig og cat infinity
|
tts <- translationList pgf ig og cat infinity
|
||||||
mkQuiz "Welcome to GF Translation Quiz." tts
|
mkQuiz cod "Welcome to GF Translation Quiz." tts
|
||||||
|
|
||||||
morphologyQuiz :: PGF -> Language -> Category -> IO ()
|
morphologyQuiz :: String -> PGF -> Language -> Category -> IO ()
|
||||||
morphologyQuiz pgf ig cat = do
|
morphologyQuiz cod pgf ig cat = do
|
||||||
tts <- morphologyList pgf ig cat infinity
|
tts <- morphologyList pgf ig cat infinity
|
||||||
mkQuiz "Welcome to GF Morphology Quiz." tts
|
mkQuiz cod "Welcome to GF Morphology Quiz." tts
|
||||||
|
|
||||||
-- | the maximal number of precompiled quiz problems
|
-- | the maximal number of precompiled quiz problems
|
||||||
infinity :: Int
|
infinity :: Int
|
||||||
|
|||||||
@@ -28,11 +28,11 @@ data CommandEnv = CommandEnv {
|
|||||||
expmacros :: Map.Map String Tree
|
expmacros :: Map.Map String Tree
|
||||||
}
|
}
|
||||||
|
|
||||||
mkCommandEnv :: (String -> String) -> PGF -> CommandEnv
|
mkCommandEnv :: String -> PGF -> CommandEnv
|
||||||
mkCommandEnv enc pgf = CommandEnv pgf (allCommands enc pgf) Map.empty Map.empty
|
mkCommandEnv enc pgf = CommandEnv pgf (allCommands enc pgf) Map.empty Map.empty
|
||||||
|
|
||||||
emptyCommandEnv :: CommandEnv
|
emptyCommandEnv :: CommandEnv
|
||||||
emptyCommandEnv = mkCommandEnv encodeUTF8 emptyPGF
|
emptyCommandEnv = mkCommandEnv "utf8" emptyPGF
|
||||||
|
|
||||||
interpretCommandLine :: (String -> String) -> CommandEnv -> String -> IO ()
|
interpretCommandLine :: (String -> String) -> CommandEnv -> String -> IO ()
|
||||||
interpretCommandLine enc env line =
|
interpretCommandLine enc env line =
|
||||||
|
|||||||
@@ -52,12 +52,16 @@ compileToPGF opts fs =
|
|||||||
link opts name gr
|
link opts name gr
|
||||||
|
|
||||||
link :: Options -> String -> SourceGrammar -> IOE PGF
|
link :: Options -> String -> SourceGrammar -> IOE PGF
|
||||||
link opts cnc gr =
|
link opts cnc gr = do
|
||||||
do gc1 <- putPointE Normal opts "linking ... " $
|
let isv = (verbAtLeast opts Normal)
|
||||||
|
gc1 <- putPointE Normal opts "linking ... " $
|
||||||
let (abs,gc0) = mkCanon2gfcc opts cnc gr
|
let (abs,gc0) = mkCanon2gfcc opts cnc gr
|
||||||
in case checkPGF gc0 of
|
in case checkPGF gc0 of
|
||||||
Ok (gc,b) -> do
|
Ok (gc,b) -> do
|
||||||
ioeIO $ putStrLn $ if b then "OK" else "Corrupted PGF"
|
case (isv,b) of
|
||||||
|
(True, True) -> ioeIO $ putStrLn "OK"
|
||||||
|
(False,True) -> return ()
|
||||||
|
_ -> ioeIO $ putStrLn $ "Corrupted PGF"
|
||||||
return gc
|
return gc
|
||||||
Bad s -> fail s
|
Bad s -> fail s
|
||||||
return $ buildParser opts $ optimize opts gc1
|
return $ buildParser opts $ optimize opts gc1
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ errors = fail . unlines
|
|||||||
|
|
||||||
-- Types
|
-- Types
|
||||||
|
|
||||||
data Mode = ModeVersion | ModeHelp | ModeInteractive | ModeCompiler
|
data Mode = ModeVersion | ModeHelp | ModeInteractive | ModeRun | ModeCompiler
|
||||||
deriving (Show,Eq,Ord)
|
deriving (Show,Eq,Ord)
|
||||||
|
|
||||||
data Verbosity = Quiet | Normal | Verbose | Debug
|
data Verbosity = Quiet | Normal | Verbose | Debug
|
||||||
@@ -413,6 +413,7 @@ optDescr =
|
|||||||
Option ['q','s'] ["quiet"] (NoArg (verbosity (Just "0"))) "Quiet, same as -v 0.",
|
Option ['q','s'] ["quiet"] (NoArg (verbosity (Just "0"))) "Quiet, same as -v 0.",
|
||||||
Option [] ["batch"] (NoArg (mode ModeCompiler)) "Run in batch compiler mode.",
|
Option [] ["batch"] (NoArg (mode ModeCompiler)) "Run in batch compiler mode.",
|
||||||
Option [] ["interactive"] (NoArg (mode ModeInteractive)) "Run in interactive mode (default).",
|
Option [] ["interactive"] (NoArg (mode ModeInteractive)) "Run in interactive mode (default).",
|
||||||
|
Option [] ["run"] (NoArg (mode ModeRun)) "Run in interactive mode, showing output only (no other messages).",
|
||||||
Option ['E'] [] (NoArg (phase Preproc)) "Stop after preprocessing (with --preproc).",
|
Option ['E'] [] (NoArg (phase Preproc)) "Stop after preprocessing (with --preproc).",
|
||||||
Option ['C'] [] (NoArg (phase Convert)) "Stop after conversion to .gf.",
|
Option ['C'] [] (NoArg (phase Convert)) "Stop after conversion to .gf.",
|
||||||
Option ['c'] [] (NoArg (phase Compile)) "Stop after compiling to .gfo (default) .",
|
Option ['c'] [] (NoArg (phase Compile)) "Stop after compiling to .gfo (default) .",
|
||||||
|
|||||||
14
src/GF/Text/Coding.hs
Normal file
14
src/GF/Text/Coding.hs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
module GF.Text.Coding where
|
||||||
|
|
||||||
|
import GF.Text.UTF8
|
||||||
|
import GF.Text.CP1251
|
||||||
|
|
||||||
|
encodeUnicode e = case e of
|
||||||
|
"utf8" -> encodeUTF8
|
||||||
|
"cp1251" -> encodeCP1251
|
||||||
|
_ -> id
|
||||||
|
|
||||||
|
decodeUnicode e = case e of
|
||||||
|
"utf8" -> decodeUTF8
|
||||||
|
"cp1251" -> decodeCP1251
|
||||||
|
_ -> id
|
||||||
60
src/GFI.hs
60
src/GFI.hs
@@ -1,4 +1,4 @@
|
|||||||
module GFI (mainGFI) where
|
module GFI (mainGFI,mainRunGFI) where
|
||||||
|
|
||||||
import GF.Command.Interpreter
|
import GF.Command.Interpreter
|
||||||
import GF.Command.Importing
|
import GF.Command.Importing
|
||||||
@@ -11,8 +11,7 @@ import GF.Infra.UseIO
|
|||||||
import GF.Infra.Option
|
import GF.Infra.Option
|
||||||
import GF.System.Readline
|
import GF.System.Readline
|
||||||
|
|
||||||
import GF.Text.UTF8 ----
|
import GF.Text.Coding
|
||||||
import GF.Text.CP1251
|
|
||||||
|
|
||||||
import PGF
|
import PGF
|
||||||
import PGF.Data
|
import PGF.Data
|
||||||
@@ -28,10 +27,17 @@ import System.CPUTime
|
|||||||
import Control.Exception
|
import Control.Exception
|
||||||
import Data.Version
|
import Data.Version
|
||||||
import GF.System.Signal
|
import GF.System.Signal
|
||||||
|
--import System.IO.Error (try)
|
||||||
|
|
||||||
import Paths_gf
|
import Paths_gf
|
||||||
|
|
||||||
|
mainRunGFI :: Options -> [FilePath] -> IO ()
|
||||||
|
mainRunGFI opts files = do
|
||||||
|
let opts1 = addOptions (modifyFlags (\f -> f{optVerbosity=Quiet})) opts
|
||||||
|
gfenv <- importInEnv emptyGFEnv opts1 files
|
||||||
|
loop opts1 gfenv
|
||||||
|
return ()
|
||||||
|
|
||||||
mainGFI :: Options -> [FilePath] -> IO ()
|
mainGFI :: Options -> [FilePath] -> IO ()
|
||||||
mainGFI opts files = do
|
mainGFI opts files = do
|
||||||
putStrLn welcome
|
putStrLn welcome
|
||||||
@@ -39,17 +45,25 @@ mainGFI opts files = do
|
|||||||
loop opts gfenv
|
loop opts gfenv
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
loopNewCPU gfenv' = do
|
loopOptNewCPU opts gfenv'
|
||||||
cpu' <- getCPUTime
|
| not (verbAtLeast opts Normal) = return gfenv'
|
||||||
putStrLnFlush (show ((cpu' - cputime gfenv') `div` 1000000000) ++ " msec")
|
| otherwise = do
|
||||||
return $ gfenv' {cputime = cpu'}
|
cpu' <- getCPUTime
|
||||||
|
putStrLnFlush (show ((cpu' - cputime gfenv') `div` 1000000000) ++ " msec")
|
||||||
|
return $ gfenv' {cputime = cpu'}
|
||||||
|
|
||||||
loop :: Options -> GFEnv -> IO GFEnv
|
loop :: Options -> GFEnv -> IO GFEnv
|
||||||
loop opts gfenv0 = do
|
loop opts gfenv0 = do
|
||||||
|
let loopNewCPU = loopOptNewCPU opts
|
||||||
|
let isv = verbAtLeast opts Normal
|
||||||
|
let ifv act = if isv then act else return ()
|
||||||
let env = commandenv gfenv0
|
let env = commandenv gfenv0
|
||||||
let sgr = sourcegrammar gfenv0
|
let sgr = sourcegrammar gfenv0
|
||||||
setCompletionFunction (Just (wordCompletion gfenv0))
|
setCompletionFunction (Just (wordCompletion gfenv0))
|
||||||
s0 <- fetchCommand (prompt env)
|
let fetch = case flag optMode opts of
|
||||||
|
ModeRun -> tryGetLine
|
||||||
|
_ -> fetchCommand (prompt env)
|
||||||
|
s0 <- fetch
|
||||||
let gfenv = gfenv0 {history = s0 : history gfenv0}
|
let gfenv = gfenv0 {history = s0 : history gfenv0}
|
||||||
let
|
let
|
||||||
enc = encode gfenv
|
enc = encode gfenv
|
||||||
@@ -62,7 +76,7 @@ loop opts gfenv0 = do
|
|||||||
|
|
||||||
case pwords of
|
case pwords of
|
||||||
|
|
||||||
"q":_ -> putStrLn "See you." >> return gfenv
|
"q":_ -> ifv (putStrLn "See you.") >> return gfenv
|
||||||
|
|
||||||
_ -> do
|
_ -> do
|
||||||
r <- runInterruptibly $ case pwords of
|
r <- runInterruptibly $ case pwords of
|
||||||
@@ -132,8 +146,16 @@ importInEnv gfenv opts files
|
|||||||
do let opts' = addOptions (setOptimization OptCSE False) opts
|
do let opts' = addOptions (setOptimization OptCSE False) opts
|
||||||
pgf0 = multigrammar (commandenv gfenv)
|
pgf0 = multigrammar (commandenv gfenv)
|
||||||
pgf1 <- importGrammar pgf0 opts' files
|
pgf1 <- importGrammar pgf0 opts' files
|
||||||
putStrLnFlush $ unwords $ "\nLanguages:" : languages pgf1
|
if (verbAtLeast opts Normal)
|
||||||
return $ gfenv { commandenv = mkCommandEnv (encode gfenv) pgf1 }
|
then putStrLnFlush $ unwords $ "\nLanguages:" : languages pgf1
|
||||||
|
else return ()
|
||||||
|
return $ gfenv { commandenv = mkCommandEnv (coding gfenv) pgf1 }
|
||||||
|
|
||||||
|
tryGetLine = do
|
||||||
|
res <- try getLine
|
||||||
|
case res of
|
||||||
|
Left e -> return "q"
|
||||||
|
Right l -> return l
|
||||||
|
|
||||||
welcome = unlines [
|
welcome = unlines [
|
||||||
" ",
|
" ",
|
||||||
@@ -168,18 +190,10 @@ data GFEnv = GFEnv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
emptyGFEnv :: GFEnv
|
emptyGFEnv :: GFEnv
|
||||||
emptyGFEnv = GFEnv emptyGrammar (mkCommandEnv encodeUTF8 emptyPGF) [] 0 "utf8"
|
emptyGFEnv = GFEnv emptyGrammar (mkCommandEnv "utf8" emptyPGF) [] 0 "utf8"
|
||||||
|
|
||||||
encode env = case coding env of
|
|
||||||
"utf8" -> encodeUTF8
|
|
||||||
"cp1251" -> encodeCP1251
|
|
||||||
_ -> id
|
|
||||||
|
|
||||||
decode env = case coding env of
|
|
||||||
"utf8" -> decodeUTF8
|
|
||||||
"cp1251" -> decodeCP1251
|
|
||||||
_ -> id
|
|
||||||
|
|
||||||
|
encode = encodeUnicode . coding
|
||||||
|
decode = decodeUnicode . coding
|
||||||
|
|
||||||
wordCompletion gfenv line0 prefix0 p =
|
wordCompletion gfenv line0 prefix0 p =
|
||||||
case wc_type (take p line) of
|
case wc_type (take p line) of
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import PGF.ShowLinearize
|
|||||||
|
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
import GF.Infra.UseIO
|
import GF.Infra.UseIO
|
||||||
|
import GF.Text.Coding
|
||||||
|
|
||||||
import System.Random
|
import System.Random
|
||||||
|
|
||||||
@@ -32,9 +33,9 @@ import Data.List (nub)
|
|||||||
|
|
||||||
-- generic quiz function
|
-- generic quiz function
|
||||||
|
|
||||||
mkQuiz :: String -> [(String,[String])] -> IO ()
|
mkQuiz :: String -> String -> [(String,[String])] -> IO ()
|
||||||
mkQuiz msg tts = do
|
mkQuiz cod msg tts = do
|
||||||
let qas = [ (q, mkAnswer as) | (q,as) <- tts]
|
let qas = [ (q, mkAnswer cod as) | (q,as) <- tts]
|
||||||
teachDialogue qas msg
|
teachDialogue qas msg
|
||||||
|
|
||||||
translationList ::
|
translationList ::
|
||||||
@@ -57,11 +58,14 @@ morphologyList pgf ig cat number = do
|
|||||||
(pws,i) <- zip ss forms, let (par,ws) = pws !! i]
|
(pws,i) <- zip ss forms, let (par,ws) = pws !! i]
|
||||||
|
|
||||||
-- | compare answer to the list of right answers, increase score and give feedback
|
-- | compare answer to the list of right answers, increase score and give feedback
|
||||||
mkAnswer :: [String] -> String -> (Integer, String)
|
mkAnswer :: String -> [String] -> String -> (Integer, String)
|
||||||
mkAnswer as s = if (elem (norml s) as)
|
mkAnswer cod as s =
|
||||||
then (1,"Yes.")
|
if (elem (norm s) as)
|
||||||
else (0,"No, not" +++ s ++ ", but" ++++ unlines as)
|
then (1,"Yes.")
|
||||||
|
else (0,"No, not" +++ s ++ ", but" ++++ enc (unlines as))
|
||||||
|
where
|
||||||
|
norm = unwords . words . decodeUnicode cod
|
||||||
|
enc = encodeUnicode cod
|
||||||
|
|
||||||
norml :: String -> String
|
|
||||||
norml = unwords . words
|
norml = unwords . words
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user