local json = require 'dkjson' local repl = require 'repl' local concat = table.concat local error = error local format = string.format local stdin, stdout = io.stdin, io.stdout local drepl = repl:clone() drepl.keep_running = true drepl:loadplugin 'autoreturn' drepl:loadplugin 'completion' drepl._features.console = true -- Lie about this to make pretty_print happy. drepl:loadplugin 'pretty_print' function drepl:displayerror(err) stdout:write(err, "\n") stdout:flush() end local function sendmsg(data) stdout:write(format("\x1b]5161;%s\x1b\\", json.encode(data))) stdout:flush() end local function readmsg() sendmsg{op="status", status="ready"} local buffer, c = {}, nil while c ~= "=" do local line = stdin:read() if line == nil then return end c = line:match("^\x1b([+=])") or error(format("Unexpected input: %q", line)) buffer[#buffer+1] = line:sub(3) end return json.decode(concat(buffer)) end local function no_op(_, args) sendmsg{id=args.id} end function drepl:showprompt(prompt) stdout:write(prompt .. ' ') stdout:flush() end function drepl:process_message() local message = readmsg() if message == nil then -- Got an EOF signal self.keep_running = false return end local method = self["drepl_" .. message.op] or no_op method(self, message) end function drepl:drepl_eval(args) sendmsg{op="status", status="rawio"} self._buffer = "" local v = self:handleline(args.code) if v == 2 then local _, err = self:compilechunk(args.code) self:displayerror(err or "incomplete input") end self:prompt(1) end function drepl:drepl_checkinput(args) local _, err = self:compilechunk(args.code) local cont = err and self:detectcontinue(err) sendmsg{ id=args.id, status=not err and "complete" or cont and "incomplete" or "invalid", prompt=err and self:getprompt(2) .. " " or nil, indent="" } end function drepl:drepl_complete(args) local prefix = args.code:sub(1, args.pos) local cands = {} self:complete( prefix, function(line) local suffix = line:sub(-1, -1) local type = (suffix == "." and "table") or (suffix=="(" and "function") or nil local _, _, cand = line:find("([%a%d_]+)[.(]?$") cands[#cands+1] = {text=cand, type=type} end ) sendmsg{ id=args.id, candidates=cands } end function drepl:main() self:prompt(1) while self.keep_running do local ok, err = pcall(self.process_message, self) if not ok then sendmsg{op="log", text=err} end end end return drepl