beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luasocket / etc / dict.lua
blob8c5b711c139946c9d2bfa5238c1aca0f2b717c4c
1 -----------------------------------------------------------------------------
2 -- Little program to download DICT word definitions
3 -- LuaSocket sample files
4 -- Author: Diego Nehab
5 -----------------------------------------------------------------------------
7 -----------------------------------------------------------------------------
8 -- Load required modules
9 -----------------------------------------------------------------------------
10 local base = _G
11 local string = require("string")
12 local table = require("table")
13 local socket = require("socket")
14 local url = require("socket.url")
15 local tp = require("socket.tp")
16 module("socket.dict")
18 -----------------------------------------------------------------------------
19 -- Globals
20 -----------------------------------------------------------------------------
21 HOST = "dict.org"
22 PORT = 2628
23 TIMEOUT = 10
25 -----------------------------------------------------------------------------
26 -- Low-level dict API
27 -----------------------------------------------------------------------------
28 local metat = { __index = {} }
30 function open(host, port)
31 local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
32 return base.setmetatable({tp = tp}, metat)
33 end
35 function metat.__index:greet()
36 return socket.try(self.tp:check(220))
37 end
39 function metat.__index:check(ok)
40 local code, status = socket.try(self.tp:check(ok))
41 return code,
42 base.tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
43 end
45 function metat.__index:getdef()
46 local line = socket.try(self.tp:receive())
47 local def = {}
48 while line ~= "." do
49 table.insert(def, line)
50 line = socket.try(self.tp:receive())
51 end
52 return table.concat(def, "\n")
53 end
55 function metat.__index:define(database, word)
56 database = database or "!"
57 socket.try(self.tp:command("DEFINE", database .. " " .. word))
58 local code, count = self:check(150)
59 local defs = {}
60 for i = 1, count do
61 self:check(151)
62 table.insert(defs, self:getdef())
63 end
64 self:check(250)
65 return defs
66 end
68 function metat.__index:match(database, strat, word)
69 database = database or "!"
70 strat = strat or "."
71 socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
72 self:check(152)
73 local mat = {}
74 local line = socket.try(self.tp:receive())
75 while line ~= '.' do
76 database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
77 if not mat[database] then mat[database] = {} end
78 table.insert(mat[database], word)
79 line = socket.try(self.tp:receive())
80 end
81 self:check(250)
82 return mat
83 end
85 function metat.__index:quit()
86 self.tp:command("QUIT")
87 return self:check(221)
88 end
90 function metat.__index:close()
91 return self.tp:close()
92 end
94 -----------------------------------------------------------------------------
95 -- High-level dict API
96 -----------------------------------------------------------------------------
97 local default = {
98 scheme = "dict",
99 host = "dict.org"
102 local function there(f)
103 if f == "" then return nil
104 else return f end
107 local function parse(u)
108 local t = socket.try(url.parse(u, default))
109 socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'")
110 socket.try(t.path, "invalid path in url")
111 local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$"))
112 socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'")
113 socket.try(arg and arg ~= "", "need at least <word> in URL")
114 t.command, t.argument = cmd, arg
115 arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
116 socket.try(t.word, "need at least <word> in URL")
117 arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
118 if cmd == "m" then
119 arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
121 string.gsub(arg, ":([^:]*)$", function(f) t.n = base.tonumber(f) end)
122 return t
125 local function tget(gett)
126 local con = open(gett.host, gett.port)
127 con:greet()
128 if gett.command == "d" then
129 local def = con:define(gett.database, gett.word)
130 con:quit()
131 con:close()
132 if gett.n then return def[gett.n]
133 else return def end
134 elseif gett.command == "m" then
135 local mat = con:match(gett.database, gett.strat, gett.word)
136 con:quit()
137 con:close()
138 return mat
139 else return nil, "invalid command" end
142 local function sget(u)
143 local gett = parse(u)
144 return tget(gett)
147 get = socket.protect(function(gett)
148 if base.type(gett) == "string" then return sget(gett)
149 else return tget(gett) end
150 end)