Almost ready for distribution...
This commit is contained in:
parent
eac26d2c8d
commit
597a062b1b
14 changed files with 323 additions and 161 deletions
184
etc/dict.lua
184
etc/dict.lua
|
@ -4,78 +4,144 @@
|
|||
-- Author: Diego Nehab
|
||||
-- RCS ID: $Id$
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Load required modules
|
||||
-----------------------------------------------------------------------------
|
||||
local socket = require("socket")
|
||||
local url = require("url")
|
||||
local tp = require("tp")
|
||||
|
||||
function get_status(sock, valid)
|
||||
local line, err = sock:receive()
|
||||
local code, par
|
||||
if not line then sock:close() return err end
|
||||
code = socket.skip(2, string.find(line, "^(%d%d%d)"))
|
||||
code = tonumber(code)
|
||||
if code ~= valid then return code end
|
||||
if code == 150 then
|
||||
par = tonumber(socket.skip(2, string.find(line, "^%d%d%d (%d*)")))
|
||||
-----------------------------------------------------------------------------
|
||||
-- Globals
|
||||
-----------------------------------------------------------------------------
|
||||
HOST = "dict.org"
|
||||
PORT = 2628
|
||||
TIMEOUT = 10
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- Low-level dict API
|
||||
-----------------------------------------------------------------------------
|
||||
local metat = { __index = {} }
|
||||
|
||||
function open(host, port)
|
||||
local tp = socket.try(tp.connect(host or HOST, port or PORT, TIMEOUT))
|
||||
return setmetatable({tp = tp}, metat)
|
||||
end
|
||||
|
||||
function metat.__index:greet()
|
||||
return socket.try(self.tp:check(220))
|
||||
end
|
||||
|
||||
function metat.__index:check(ok)
|
||||
local code, status = socket.try(self.tp:check(ok))
|
||||
return code, tonumber(socket.skip(2, string.find(status, "^%d%d%d (%d*)")))
|
||||
end
|
||||
|
||||
function metat.__index:getdef()
|
||||
local line = socket.try(self.tp:receive())
|
||||
local def = {}
|
||||
while line ~= "." do
|
||||
table.insert(def, line)
|
||||
line = socket.try(self.tp:receive())
|
||||
end
|
||||
return nil, par
|
||||
return table.concat(def, "\n")
|
||||
end
|
||||
|
||||
function get_def(sock)
|
||||
local line, err = sock:receive()
|
||||
local def = ""
|
||||
while (not err) and line ~= "." do
|
||||
def = def .. line .. "\n"
|
||||
line, err = sock:receive()
|
||||
function metat.__index:define(database, word)
|
||||
database = database or "!"
|
||||
socket.try(self.tp:command("DEFINE", database .. " " .. word))
|
||||
local code, count = self:check(150)
|
||||
local defs = {}
|
||||
for i = 1, count do
|
||||
self:check(151)
|
||||
table.insert(defs, self:getdef())
|
||||
end
|
||||
if err then sock:close() return nil, err
|
||||
else return def end
|
||||
self:check(250)
|
||||
return defs
|
||||
end
|
||||
|
||||
function dict_open()
|
||||
local sock, err = socket.connect("dict.org", 2628)
|
||||
if not sock then return nil, err end
|
||||
sock:settimeout(10)
|
||||
local code, par = get_status(sock, 220)
|
||||
if code then return nil, code end
|
||||
return sock
|
||||
end
|
||||
|
||||
function dict_define(sock, word, dict)
|
||||
dict = dict or "web1913"
|
||||
sock:send("DEFINE " .. dict .. " " .. word .. "\r\n")
|
||||
local code, par = get_status(sock, 150)
|
||||
if code or not par then return nil, code end
|
||||
local defs = ""
|
||||
for i = 1, par do
|
||||
local def
|
||||
code, par = get_status(sock, 151)
|
||||
if code then return nil, code end
|
||||
def, err = get_def(sock)
|
||||
if not def then return nil, err end
|
||||
defs = defs .. def .. "\n"
|
||||
function metat.__index:match(database, strat, word)
|
||||
database = database or "!"
|
||||
strat = strat or "."
|
||||
socket.try(self.tp:command("MATCH", database .." ".. strat .." ".. word))
|
||||
self:check(152)
|
||||
local mat = {}
|
||||
local line = socket.try(self.tp:receive())
|
||||
while line ~= '.' do
|
||||
database, word = socket.skip(2, string.find(line, "(%S+) (.*)"))
|
||||
if not mat[database] then mat[database] = {} end
|
||||
table.insert(mat[database], word)
|
||||
line = socket.try(self.tp:receive())
|
||||
end
|
||||
code, par = get_status(sock, 250)
|
||||
if code then return nil, code end
|
||||
return string.gsub(defs, "%s%s$", "")
|
||||
self:check(250)
|
||||
return mat
|
||||
end
|
||||
|
||||
function dict_close(sock)
|
||||
sock:send("QUIT\r\n")
|
||||
local code, par = get_status(sock, 221)
|
||||
sock:close()
|
||||
return code
|
||||
function metat.__index:quit()
|
||||
self.tp:command("QUIT")
|
||||
return self:check(221)
|
||||
end
|
||||
|
||||
function dict_get(word, dict)
|
||||
local sock, err = dict_open()
|
||||
if not sock then return nil, err end
|
||||
local defs, err = dict_define(sock, word, dict)
|
||||
dict_close(sock)
|
||||
return defs, err
|
||||
function metat.__index:close()
|
||||
return self.tp:close()
|
||||
end
|
||||
|
||||
if arg and arg[1] then
|
||||
defs, err = dict_get(arg[1], arg[2])
|
||||
print(defs or err)
|
||||
else
|
||||
io.write("Usage:\n lua dict.lua <word> [<dictionary>]\n")
|
||||
-----------------------------------------------------------------------------
|
||||
-- High-level dict API
|
||||
-----------------------------------------------------------------------------
|
||||
local default = {
|
||||
scheme = "dict",
|
||||
host = "dict.org"
|
||||
}
|
||||
|
||||
local function there(f)
|
||||
if f == "" then return nil
|
||||
else return f end
|
||||
end
|
||||
|
||||
local function parse(u)
|
||||
local t = socket.try(url.parse(u, default))
|
||||
socket.try(t.scheme == "dict", "invalid scheme '" .. t.scheme .. "'")
|
||||
socket.try(t.path, "invalid path in url")
|
||||
local cmd, arg = socket.skip(2, string.find(t.path, "^/(.)(.*)$"))
|
||||
socket.try(cmd == "d" or cmd == "m", "<command> should be 'm' or 'd'")
|
||||
socket.try(arg and arg ~= "", "need at least <word> in URL")
|
||||
t.command, t.argument = cmd, arg
|
||||
arg = string.gsub(arg, "^:([^:]+)", function(f) t.word = f end)
|
||||
socket.try(t.word, "need at least <word> in URL")
|
||||
arg = string.gsub(arg, "^:([^:]*)", function(f) t.database = there(f) end)
|
||||
if cmd == "m" then
|
||||
arg = string.gsub(arg, "^:([^:]*)", function(f) t.strat = there(f) end)
|
||||
end
|
||||
string.gsub(arg, ":([^:]*)$", function(f) t.n = tonumber(f) end)
|
||||
return t
|
||||
end
|
||||
|
||||
local function tget(gett)
|
||||
local con = open(gett.host, gett.port)
|
||||
con:greet()
|
||||
if gett.command == "d" then
|
||||
local def = con:define(gett.database, gett.word)
|
||||
con:quit()
|
||||
con:close()
|
||||
if gett.n then return def[gett.n]
|
||||
else return def end
|
||||
elseif gett.command == "m" then
|
||||
local mat = con:match(gett.database, gett.strat, gett.word)
|
||||
con:quit()
|
||||
con:close()
|
||||
return mat
|
||||
else return nil, "invalid command" end
|
||||
end
|
||||
|
||||
local function sget(u)
|
||||
local gett = parse(u)
|
||||
return tget(gett)
|
||||
end
|
||||
|
||||
--function socket.protect(f) return f end
|
||||
get = socket.protect(function(gett)
|
||||
if type(gett) == "string" then return sget(gett)
|
||||
else return tget(gett) end
|
||||
end)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue