aboutsummaryrefslogtreecommitdiff
path: root/etc/dict.lua
diff options
context:
space:
mode:
authorDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-17 21:46:22 +0000
committerDiego Nehab <diego@tecgraf.puc-rio.br>2004-06-17 21:46:22 +0000
commit597a062b1bc38488df1363995eece8a9f19c7111 (patch)
treeba4ccaa8be98d1100aed63abb9c42c099f2c41bb /etc/dict.lua
parenteac26d2c8dafab604ef2e97e504326cfaf1033cf (diff)
downloadluasocket-597a062b1bc38488df1363995eece8a9f19c7111.tar.gz
luasocket-597a062b1bc38488df1363995eece8a9f19c7111.tar.bz2
luasocket-597a062b1bc38488df1363995eece8a9f19c7111.zip
Almost ready for distribution...
Diffstat (limited to 'etc/dict.lua')
-rw-r--r--etc/dict.lua182
1 files changed, 124 insertions, 58 deletions
diff --git a/etc/dict.lua b/etc/dict.lua
index dd001cf..b9247dc 100644
--- a/etc/dict.lua
+++ b/etc/dict.lua
@@ -4,78 +4,144 @@
4-- Author: Diego Nehab 4-- Author: Diego Nehab
5-- RCS ID: $Id$ 5-- RCS ID: $Id$
6----------------------------------------------------------------------------- 6-----------------------------------------------------------------------------
7
8-----------------------------------------------------------------------------
9-- Load required modules
10-----------------------------------------------------------------------------
7local socket = require("socket") 11local socket = require("socket")
12local url = require("url")
13local tp = require("tp")
8 14
9function get_status(sock, valid) 15-----------------------------------------------------------------------------
10 local line, err = sock:receive() 16-- Globals
11 local code, par 17-----------------------------------------------------------------------------
12 if not line then sock:close() return err end 18HOST = "dict.org"
13 code = socket.skip(2, string.find(line, "^(%d%d%d)")) 19PORT = 2628
14 code = tonumber(code) 20TIMEOUT = 10
15 if code ~= valid then return code end 21
16 if code == 150 then 22-----------------------------------------------------------------------------
17 par = tonumber(socket.skip(2, string.find(line, "^%d%d%d (%d*)"))) 23-- Low-level dict API
18 end 24-----------------------------------------------------------------------------
19 return nil, par 25local metat = { __index = {} }
26
27function open(host, port)
28 local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
29 return setmetatable({tp = tp}, metat)
20end 30end
21 31
22function get_def(sock) 32function metat.__index:greet()
23 local line, err = sock:receive() 33 return socket.try(self.tp:check(220))
24 local def = "" 34end
25 while (not err) and line ~= "." do 35
26 def = def .. line .. "\n" 36function metat.__index:check(ok)
27 line, err = sock:receive() 37 local code, status = socket.try(self.tp:check(ok))
38 return code, tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
39end
40
41function metat.__index:getdef()
42 local line = socket.try(self.tp:receive())
43 local def = {}
44 while line ~= "." do
45 table.insert(def, line)
46 line = socket.try(self.tp:receive())
28 end 47 end
29 if err then sock:close() return nil, err 48 return table.concat(def, "\n")
30 else return def end
31end 49end
32 50
33function dict_open() 51function metat.__index:define(database, word)
34 local sock, err = socket.connect("dict.org", 2628) 52 database = database or "!"
35 if not sock then return nil, err end 53 socket.try(self.tp:command("DEFINE", database .. " " .. word))
36 sock:settimeout(10) 54 local code, count = self:check(150)
37 local code, par = get_status(sock, 220) 55 local defs = {}
38 if code then return nil, code end 56 for i = 1, count do
39 return sock 57 self:check(151)
58 table.insert(defs, self:getdef())
59 end
60 self:check(250)
61 return defs
40end 62end
41 63
42function dict_define(sock, word, dict) 64function metat.__index:match(database, strat, word)
43 dict = dict or "web1913" 65 database = database or "!"
44 sock:send("DEFINE " .. dict .. " " .. word .. "\r\n") 66 strat = strat or "."
45 local code, par = get_status(sock, 150) 67 socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
46 if code or not par then return nil, code end 68 self:check(152)
47 local defs = "" 69 local mat = {}
48 for i = 1, par do 70 local line = socket.try(self.tp:receive())
49 local def 71 while line ~= '.' do
50 code, par = get_status(sock, 151) 72 database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
51 if code then return nil, code end 73 if not mat[database] then mat[database] = {} end
52 def, err = get_def(sock) 74 table.insert(mat[database], word)
53 if not def then return nil, err end 75 line = socket.try(self.tp:receive())
54 defs = defs .. def .. "\n"
55 end 76 end
56 code, par = get_status(sock, 250) 77 self:check(250)
57 if code then return nil, code end 78 return mat
58 return string.gsub(defs, "%s%s$", "") 79end
80
81function metat.__index:quit()
82 self.tp:command("QUIT")
83 return self:check(221)
84end
85
86function metat.__index:close()
87 return self.tp:close()
59end 88end
60 89
61function dict_close(sock) 90-----------------------------------------------------------------------------
62 sock:send("QUIT\r\n") 91-- High-level dict API
63 local code, par = get_status(sock, 221) 92-----------------------------------------------------------------------------
64 sock:close() 93local default = {
65 return code 94 scheme = "dict",
95 host = "dict.org"
96}
97
98local function there(f)
99 if f == "" then return nil
100 else return f end
66end 101end
67 102
68function dict_get(word, dict) 103local function parse(u)
69 local sock, err = dict_open() 104 local t = socket.try(url.parse(u, default))
70 if not sock then return nil, err end 105 socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'")
71 local defs, err = dict_define(sock, word, dict) 106 socket.try(t.path, "invalid path in url")
72 dict_close(sock) 107 local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$"))
73 return defs, err 108 socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'")
109 socket.try(arg and arg ~= "", "need at least <word> in URL")
110 t.command, t.argument = cmd, arg
111 arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
112 socket.try(t.word, "need at least <word> in URL")
113 arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
114 if cmd == "m" then
115 arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
116 end
117 string.gsub(arg, ":([^:]*)$", function(f) t.n = tonumber(f) end)
118 return t
74end 119end
75 120
76if arg and arg[1] then 121local function tget(gett)
77 defs, err = dict_get(arg[1], arg[2]) 122 local con = open(gett.host, gett.port)
78 print(defs or err) 123 con:greet()
79else 124 if gett.command == "d" then
80 io.write("Usage:\n lua dict.lua <word> [<dictionary>]\n") 125 local def = con:define(gett.database, gett.word)
126 con:quit()
127 con:close()
128 if gett.n then return def[gett.n]
129 else return def end
130 elseif gett.command == "m" then
131 local mat = con:match(gett.database, gett.strat, gett.word)
132 con:quit()
133 con:close()
134 return mat
135 else return nil, "invalid command" end
81end 136end
137
138local function sget(u)
139 local gett = parse(u)
140 return tget(gett)
141end
142
143--function socket.protect(f) return f end
144get = socket.protect(function(gett)
145 if type(gett) == "string" then return sget(gett)
146 else return tget(gett) end
147end)