123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- -----------------------------------------------------------------------------
- -- Little program to download DICT word definitions
- -- LuaSocket sample files
- -- Author: Diego Nehab
- -----------------------------------------------------------------------------
- -----------------------------------------------------------------------------
- -- Load required modules
- -----------------------------------------------------------------------------
- local base = _G
- local string = require("string")
- local table = require("table")
- local socket = require("socket")
- local url = require("socket.url")
- local tp = require("socket.tp")
- module("socket.dict")
- -----------------------------------------------------------------------------
- -- 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 base.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,
- base.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 table.concat(def, "\n")
- end
- 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
- self:check(250)
- return defs
- end
- 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
- self:check(250)
- return mat
- end
- function metat.__index:quit()
- self.tp:command("QUIT")
- return self:check(221)
- end
- function metat.__index:close()
- return self.tp:close()
- end
- -----------------------------------------------------------------------------
- -- 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 = base.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
- get = socket.protect(function(gett)
- if base.type(gett) == "string" then return sget(gett)
- else return tget(gett) end
- end)
|