Skip to content

Commit

Permalink
logic to start/stop repl
Browse files Browse the repository at this point in the history
  • Loading branch information
atinylittleshell committed Apr 8, 2024
1 parent e629818 commit dfd58cf
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 15 deletions.
1 change: 1 addition & 0 deletions examples/python.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
i = 30
26 changes: 15 additions & 11 deletions lua/comment_repl.lua
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
local commands = require("comment_repl.commands")

---@class Config
local config = {}
local log = require("comment_repl.log")
local repl_manager = require("comment_repl.repl_manager")
local config = require("comment_repl.config")

---@class CommentREPL
local M = {}

---@type Config
M.config = config

---@param args Config?
M.setup = function(args)
M.config = vim.tbl_deep_extend("force", M.config, args or {})
end
config = vim.tbl_deep_extend("force", config, args or {})

local supported_repls = table.concat(vim.tbl_keys(config.repls), ",")
log.fmt_info("Setting up comment-repl.nvim for: %s", supported_repls)

local autocmds = vim.api.nvim_create_augroup("CommentREPL", { clear = true })

M.execute = function()
return commands.execute()
vim.api.nvim_create_autocmd("BufUnload", {
group = autocmds,
callback = function(ev)
repl_manager.stop(ev.buf)
end,
})
end

return M
21 changes: 19 additions & 2 deletions lua/comment_repl/commands.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
local log = require("comment_repl.log")
local config = require("comment_repl.config")
local repl_manager = require("comment_repl.repl_manager")

---@class Commands
local M = {}

---@return string
---@return nil
M.execute = function()
return "Hello, World!"
local repl_config = config.repls[vim.bo.filetype]
if not repl_config then
log.fmt_error("No REPL configured for %s", vim.bo.filetype)
vim.notify("No REPL configured for " .. vim.bo.filetype, vim.log.levels.ERROR)
return
end

local bufnr = vim.api.nvim_get_current_buf()
repl_manager.start(bufnr, repl_config)
end

---@return nil
M.view_log = function()
log.view_log()
end

return M
13 changes: 13 additions & 0 deletions lua/comment_repl/config.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---@class Config
---@field repls table<string, LanguageConfig>
local M = {
repls = {
python = {
display = "Python",
cmd = "python",
args = { "-i" },
},
},
}

return M
154 changes: 154 additions & 0 deletions lua/comment_repl/log.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
-- log.lua
--
-- Inspired by rxi/log.lua
-- Modified by tjdevries and can be found at github.com/tjdevries/vlog.nvim
--
-- This library is free software; you can redistribute it and/or modify it
-- under the terms of the MIT license. See LICENSE for details.

-- User configuration section
local default_config = {
-- Name of the plugin. Prepended to log messages
plugin = "comment-repl.nvim",

-- Should print the output to neovim while running
use_console = false,

-- Should highlighting be used in console (using echohl)
highlights = true,

-- Should write to a file
use_file = true,

-- Any messages above this level will be logged.
level = "info",

-- Level configuration
modes = {
{ name = "trace", hl = "Comment" },
{ name = "debug", hl = "Comment" },
{ name = "info", hl = "None" },
{ name = "warn", hl = "WarningMsg" },
{ name = "error", hl = "ErrorMsg" },
{ name = "fatal", hl = "ErrorMsg" },
},

-- Can limit the number of decimals displayed for floats
float_precision = 0.01,
}

-- {{{ NO NEED TO CHANGE
local log = {}

local unpack = unpack or table.unpack

log.new = function(config, standalone)
config = vim.tbl_deep_extend("force", default_config, config)

local outfile =
string.format("%s/%s.log", vim.api.nvim_call_function("stdpath", { "data" }), config.plugin)

local obj
if standalone then
obj = log
else
obj = {}
end

local levels = {}
for i, v in ipairs(config.modes) do
levels[v.name] = i
end

local round = function(x, increment)
increment = increment or 1
x = x / increment
return (x > 0 and math.floor(x + 0.5) or math.ceil(x - 0.5)) * increment
end

local make_string = function(...)
local t = {}
for i = 1, select("#", ...) do
local x = select(i, ...)

if type(x) == "number" and config.float_precision then
x = tostring(round(x, config.float_precision))
elseif type(x) == "table" then
x = vim.inspect(x)
else
x = tostring(x)
end

t[#t + 1] = x
end
return table.concat(t, " ")
end

local log_at_level = function(level, level_config, message_maker, ...)
-- Return early if we're below the config.level
if level < levels[config.level] then
return
end
local nameupper = level_config.name:upper()

local msg = message_maker(...)
local info = debug.getinfo(2, "Sl")
local lineinfo = info.short_src .. ":" .. info.currentline

-- Output to console
if config.use_console then
local console_string =
string.format("[%-6s%s] %s: %s", nameupper, os.date("%H:%M:%S"), lineinfo, msg)

if config.highlights and level_config.hl then
vim.cmd(string.format("echohl %s", level_config.hl))
end

local split_console = vim.split(console_string, "\n")
for _, v in ipairs(split_console) do
vim.cmd(string.format([[echom "[%s] %s"]], config.plugin, vim.fn.escape(v, '"')))
end

if config.highlights and level_config.hl then
vim.cmd("echohl NONE")
end
end

-- Output to log file
if config.use_file then
local fp = io.open(outfile, "a")
assert(fp)

local str = string.format("[%-6s%s] %s: %s\n", nameupper, os.date(), lineinfo, msg)
fp:write(str)
fp:close()
end
end

obj["view_log"] = function()
vim.cmd("tabnew " .. outfile)
end

for i, x in ipairs(config.modes) do
obj[x.name] = function(...)
return log_at_level(i, x, make_string, ...)
end

obj[("fmt_%s"):format(x.name)] = function(...)
return log_at_level(i, x, function(...)
local passed = { ... }
local fmt = table.remove(passed, 1)
local inspected = {}
for _, v in ipairs(passed) do
table.insert(inspected, vim.inspect(v))
end
return string.format(fmt, unpack(inspected))
end, ...)
end
end
end

log.new(default_config, true)
-- }}}

return log
67 changes: 67 additions & 0 deletions lua/comment_repl/repl_manager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
local log = require("comment_repl.log")

---@class LanguageConfig
---@field display string
---@field cmd string
---@field args table<string>

---@class REPLManager
local M = {}

---@class REPLInstance
---@field config LanguageConfig
---@field process uv_process_t
---@field stdin uv_pipe_t
---@field stdout uv_pipe_t
---@field stderr uv_pipe_t

---@type table<number, REPLInstance>
local buf_to_repl = {}

---@param bufnr number
---@param repl_config LanguageConfig
M.start = function(bufnr, repl_config)
if buf_to_repl[bufnr] then
log.fmt_warn("REPL already started for buffer %d", bufnr)
return
end

local stdin = vim.loop.new_pipe(false)
local stdout = vim.loop.new_pipe(false)
local stderr = vim.loop.new_pipe(false)
local process = vim.loop.spawn(repl_config.cmd, {
args = repl_config.args,
stdio = { stdin, stdout, stderr },
}, function()
stdin:close()
stdout:close()
stderr:close()
buf_to_repl[bufnr] = nil
end)

assert(process)

buf_to_repl[bufnr] = {
config = repl_config,
process = process,
stdin = stdin,
stdout = stdout,
stderr = stderr,
}

log.fmt_info("%s REPL started for buffer %d", repl_config.display, bufnr)
end

---@param bufnr number
M.stop = function(bufnr)
if buf_to_repl[bufnr] then
buf_to_repl[bufnr].process:kill("sigterm")
buf_to_repl[bufnr] = nil

log.fmt_info("REPL stopped for buffer %d", bufnr)
else
log.fmt_debug("Can't stop REPL because it's not started for buffer %d", bufnr)
end
end

return M
3 changes: 2 additions & 1 deletion plugin/comment_repl.lua
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
vim.api.nvim_create_user_command("ExecuteCommentREPL", require("plugin.comment_repl").execute, {})
vim.api.nvim_create_user_command("CommentREPLExecute", require("comment_repl.commands").execute, {})
vim.api.nvim_create_user_command("CommentREPLLog", require("comment_repl.commands").view_log, {})
2 changes: 1 addition & 1 deletion tests/comment_repl/comment_repl_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ local plugin = require("comment_repl")

describe("setup", function()
it("works with default", function()
assert(plugin.execute() == "Hello, World!", "Expected 'Hello, World!'")
plugin.setup()
end)
end)

0 comments on commit dfd58cf

Please sign in to comment.