summaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/MainFastCGI.hs39
-rw-r--r--src/server/gf-client.html63
-rw-r--r--src/server/gf-server-jsapi.js6
-rw-r--r--src/server/gf-server.cabal1
-rw-r--r--src/server/translator.css55
-rw-r--r--src/server/translator.js12
6 files changed, 140 insertions, 36 deletions
diff --git a/src/server/MainFastCGI.hs b/src/server/MainFastCGI.hs
index d678c1579..230e09b00 100644
--- a/src/server/MainFastCGI.hs
+++ b/src/server/MainFastCGI.hs
@@ -11,6 +11,7 @@ import qualified Codec.Binary.UTF8.String as UTF8 (encodeString)
import Control.Exception
import Control.Monad
import Data.Dynamic
+import qualified Data.Map as Map
import Data.Maybe
@@ -31,12 +32,13 @@ cgiMain :: PGF -> CGI CGIResult
cgiMain pgf =
do path <- pathInfo
json <- case path of
- "/parse" -> return (doParse pgf) `ap` getText `ap` getCat `ap` getFrom
- "/linearize" -> return (doLinearize pgf) `ap` getTree `ap` getTo
- "/translate" -> return (doTranslate pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getTo
- "/categories" -> return $ doCategories pgf
- "/languages" -> return $ doLanguages pgf
- _ -> throwCGIError 404 "Not Found" ["Resource not found: " ++ path]
+ "/parse" -> return (doParse pgf) `ap` getText `ap` getCat `ap` getFrom
+ "/complete" -> return (doComplete pgf) `ap` getText `ap` getCat `ap` getFrom
+ "/linearize" -> return (doLinearize pgf) `ap` getTree `ap` getTo
+ "/translate" -> return (doTranslate pgf) `ap` getText `ap` getCat `ap` getFrom `ap` getTo
+ "/categories" -> return $ doCategories pgf
+ "/languages" -> return $ doLanguages pgf
+ _ -> throwCGIError 404 "Not Found" ["Resource not found: " ++ path]
outputJSON json
where
getText :: CGI String
@@ -80,6 +82,9 @@ doParse :: PGF -> String -> Maybe PGF.Category -> Maybe PGF.Language -> JSValue
doParse pgf input mcat mfrom = showJSON $ toJSObject $
[(from, map PGF.showTree trees) | (from,trees) <- parse' pgf input mcat mfrom]
+doComplete :: PGF -> String -> Maybe PGF.Category -> Maybe PGF.Language -> JSValue
+doComplete pgf input mcat mfrom = showJSON $ toJSObject $ complete' pgf input mcat mfrom
+
doLinearize :: PGF -> PGF.Tree -> Maybe PGF.Language -> JSValue
doLinearize pgf tree mto = showJSON $ toJSObject $ linearize' pgf mto tree
@@ -96,10 +101,24 @@ doCategories pgf = showJSON (PGF.categories pgf)
parse' :: PGF -> String -> Maybe PGF.Category -> Maybe PGF.Language -> [(PGF.Language,[PGF.Tree])]
parse' pgf input mcat mfrom =
- case mfrom of
- Nothing -> PGF.parseAllLang pgf cat input
- Just from -> [(from, PGF.parse pgf from cat input)]
- where cat = fromMaybe (PGF.startCat pgf) mcat
+ [(from,ts) | from <- froms, PGF.canParse pgf from, let ts = PGF.parse pgf from cat input, not (null ts)]
+ where froms = maybe (PGF.languages pgf) (:[]) mfrom
+ cat = fromMaybe (PGF.startCat pgf) mcat
+
+complete' :: PGF -> String -> Maybe PGF.Category -> Maybe PGF.Language -> [(PGF.Language,[String])]
+complete' pgf input mcat mfrom =
+ [(from,ss) | from <- froms, PGF.canParse pgf from, let ss = complete pgf from cat input, not (null ss)]
+ where froms = maybe (PGF.languages pgf) (:[]) mfrom
+ cat = fromMaybe (PGF.startCat pgf) mcat
+
+complete :: PGF -> PGF.Language -> PGF.Category -> String -> [String]
+complete pgf from cat input =
+ let ws = words input
+ prefix = "" -- FIXME
+ state0 = PGF.initState pgf from cat
+ state = foldl PGF.nextState state0 ws
+ compls = PGF.getCompletions state prefix
+ in Map.keys compls
linearize' :: PGF -> Maybe PGF.Language -> PGF.Tree -> [(PGF.Language,String)]
linearize' pgf mto tree =
diff --git a/src/server/gf-client.html b/src/server/gf-client.html
index 4516d7e1e..a3558e25c 100644
--- a/src/server/gf-client.html
+++ b/src/server/gf-client.html
@@ -13,10 +13,11 @@
var input = document.getElementById('inputText').value;
var fromLang = document.getElementById('fromLang').value;
var toLang = document.getElementById('toLang').value;
- var output = document.getElementById('output');
+ var output = document.getElementById('translation');
+
var callback = function(translation) {
- removeChildren(output);
- output.appendChild(formatTranslation(translation));
+ clearTranslation();
+ output.appendChild(formatTranslation(translation));
};
gf.translate(input, fromLang, toLang, '', callback);
}
@@ -32,23 +33,55 @@
}
}
+ function updateCompletion() {
+ var input = document.getElementById('inputText').value;
+ var fromLang = document.getElementById('fromLang').value;
+ var completions = document.getElementById('completion');
+
+// if (document.getElementById('enableCompletion').checked) {
+ var callback = function(output) {
+ clearCompletion();
+ completions.appendChild(formatCompletions(output));
+ };
+ gf.complete(input, fromLang, '', callback);
+// }
+ }
+
+ function update() {
+ updateCompletion();
+ updateTranslation();
+ }
+
+ function clearTranslation() {
+ var output = document.getElementById('translation');
+ removeChildren(output);
+ }
+
+ function clearCompletion() {
+ var completions = document.getElementById('completion');
+ removeChildren(completions);
+ }
+
function initialize() {
- gf.getLanguages(populateLangs);
+ gf.languages(populateLangs);
}
</script>
<title>AJAX GF Translator</title>
</head>
<body onload="initialize()">
- <form id="translate" onsubmit="updateTranslation(); return false;">
- <p>
- <input type="text" name="inputText" id="inputText" value="this cheese is warm" size="50" />
- </p>
- <p>
- From: <select name="fromLang" id="fromLang" onchange="updateTranslation()"><option value="">Any language</option></select>
- To: <select name="toLang" id="toLang" onchange="updateTranslation()"><option value="">All languages</option></select>
- <input type="submit" value="Translate" />
- </p>
- </form>
- <div id="output"></div>
+ <div id="translator">
+ <form onsubmit="update(); return false;">
+ <p>
+ <input type="text" id="inputText" value="this cheese is warm" size="50" onkeyup="update()"/>
+ </p>
+ <p>
+ <label>From: <select id="fromLang" onchange="update()"><option value="">Any language</option></select></label>
+ <label>To: <select id="toLang" onchange="update()"><option value="">All languages</option></select></label>
+ <input type="submit" value="Translate" />
+ </p>
+ </form>
+ <div id="completion"></div>
+ <div id="translation"></div>
+ </div>
</body>
</html>
diff --git a/src/server/gf-server-jsapi.js b/src/server/gf-server-jsapi.js
index 9a2096532..dfa50c2f7 100644
--- a/src/server/gf-server-jsapi.js
+++ b/src/server/gf-server-jsapi.js
@@ -4,7 +4,11 @@ gf.translate = function (input,from,to,cat,callback) {
gf.httpGetText("gf.fcgi/translate?input="+escape(input)+"&from="+escape(from)+"&to="+escape(to)+"&cat="+escape(cat), function (output) { callback(gf.readJSON(output)); });
};
-gf.getLanguages = function (callback) {
+gf.complete = function (input,from,cat,callback) {
+ gf.httpGetText("gf.fcgi/complete?input="+escape(input)+"&from="+escape(from)+"&cat="+escape(cat), function (output) { callback(gf.readJSON(output)); });
+};
+
+gf.languages = function (callback) {
gf.httpGetText("gf.fcgi/languages", function (output) { callback(gf.readJSON(output)); });
};
diff --git a/src/server/gf-server.cabal b/src/server/gf-server.cabal
index f6104e481..67935e491 100644
--- a/src/server/gf-server.cabal
+++ b/src/server/gf-server.cabal
@@ -11,6 +11,7 @@ executable gf.fcgi
old-time,
unix,
directory,
+ containers,
gf,
cgi,
fastcgi,
diff --git a/src/server/translator.css b/src/server/translator.css
index f7f771927..d4fb7be1f 100644
--- a/src/server/translator.css
+++ b/src/server/translator.css
@@ -1,10 +1,12 @@
body {
color: black;
background-color: white;
+ font-family: sans-serif;
}
dl {
-
+ margin: 0;
+ padding: 0;
}
dt {
@@ -17,6 +19,29 @@ dl dd {
padding: 0;
}
+ul {
+ margin: 0;
+ padding: 0;
+}
+
+li {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+/* Translator widget */
+
+#translator {
+
+}
+
+/* Translations */
+
+#translation {
+ clear: both;
+}
+
dl.fromLang dt {
display: none;
}
@@ -32,23 +57,33 @@ dl.toLang dt {
display: block;
float: left;
width: 5em;
+ font-size: 80%;
+ padding: 1px 0;
}
-
dl.toLang dd {
border-width: 0 0 1px 0;
border-style: solid;
border-color: #c0c0c0;
+ padding: 0.2em 0;
}
+/* Completions */
-ul {
- margin: 0;
- padding: 0;
+#completion {
+ font-size: 80%;
+ color: #c0c0c0;
+ white-space: nowrap;
+ width: 100%;
+ overflow: hidden;
+}
+
+#completion dt {
+ display: none;
+}
+
+#completion li {
+ display: inline;
+ padding: 0 0.1em;
}
-li {
- list-style-type: none;
- margin: 0;
- padding: 0;
-} \ No newline at end of file
diff --git a/src/server/translator.js b/src/server/translator.js
index 31da04290..96acd52d2 100644
--- a/src/server/translator.js
+++ b/src/server/translator.js
@@ -17,6 +17,18 @@ function formatTranslation (outputs) {
return dl1;
}
+function formatCompletions (compls) {
+ var dl = document.createElement("dl");
+ for (var fromLang in compls) {
+ var ul = document.createElement("ul");
+ for (var i in compls[fromLang]) {
+ addItem(ul, document.createTextNode(compls[fromLang][i]));
+ }
+ addDefinition(dl, document.createTextNode(fromLang), ul);
+ }
+ return dl;
+}
+
/* DOM utilities for specific tags */
function addDefinition (dl, t, d) {