Last active
October 30, 2024 19:01
-
-
Save itsfrank/bad1f494798df5370e5f8236757bbf2a to your computer and use it in GitHub Desktop.
localhost tcp based notification system for neovim
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- some place where you define user commands | |
---@type uv_tcp_t? | |
local notify_server = nil | |
vim.api.nvim_create_user_command("StartNotifyServer", function() | |
if notify_server and not notify_server:is_closing() then | |
return | |
end | |
local try_notify_server, err = require("notify_server").start_server() | |
if err then | |
error(err) | |
end | |
notify_server = try_notify_server | |
end, {}) | |
vim.api.nvim_create_user_command("StopNotifyServer", function() | |
if notify_server and not notify_server:is_closing() then | |
notify_server:close() | |
end | |
end, {}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# put this on your path | |
# check var | |
port=${NOTIFY_PORT:-34567} | |
case $# in | |
0) | |
# do nothing | |
;; | |
1) | |
echo "{\"evt\": \"$1\"}" | nc localhost "$port" >/dev/null 2>&1 | |
;; | |
2) | |
echo "{\"evt\": \"$1\", \"msg\": \"$2\"}" | nc localhost "$port" >/dev/null 2>&1 | |
;; | |
esac | |
# the nc call might fail if ther eis no server listening, but this script doesnt consider that a failure | |
# I want to use this script in command chains, it should not caus echains to fail | |
exit 0 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
---@param host string | |
---@param port number | |
---@param on_data? fun(data: string, sock: uv_tcp_t) | |
---@param on_err? fun(data: string, sock: uv_tcp_t) | |
---@return uv_tcp_t?, string? | |
local function create_tcp_server(host, port, on_data, on_err) | |
local server = vim.uv.new_tcp() | |
local _, err = server:bind(host, port) | |
if err ~= nil then | |
return nil, "start server failed for '" .. host .. ":" .. tostring(port) .. "', err: " .. err | |
end | |
_, err = server:listen(128, function(err1) | |
assert(not err1, err1) | |
local sock = vim.uv.new_tcp() | |
server:accept(sock) | |
sock:read_start(function(err2, chunk) | |
if err2 then | |
error(err2) | |
end | |
if err2 and on_err ~= nil then | |
on_err(err2, sock) | |
elseif chunk and on_data ~= nil then | |
on_data(chunk, sock) | |
end | |
if not sock:is_closing() then | |
sock:close() | |
end | |
end) | |
end) | |
if err ~= nil then | |
return nil, "start server failed for '" .. host .. ":" .. tostring(port) .. "', err: " .. err | |
end | |
return server | |
end | |
--- start a tcp server that will notify based on tcp messages to localhost @ port env.NOTIFY_PORT | |
--- messages are json and take form {"evt": "info|warn|err", "msg": "<your message>"} | |
--- they are fed to vim.notify with the matching level | |
---@return uv_tcp_t?, string? | |
local function notify_start_server() | |
local notify_port = tonumber(vim.env.NOTIFY_PORT) or 34567 | |
local notify_server, err = create_tcp_server("0.0.0.0", notify_port, function(data, sock) | |
local ok, json = pcall(function() | |
return vim.json.decode(data) | |
end) | |
local lvl = vim.log.levels[string.upper(json.evt or "")] | |
local msg = json.msg | |
if ok and lvl ~= nil and msg ~= nil then | |
vim.schedule(function() | |
vim.notify(msg, lvl) | |
end) | |
end | |
sock:write("ack") | |
end) | |
if err ~= nil then | |
return nil, err | |
end | |
assert(notify_server ~= nil) | |
vim.api.nvim_create_autocmd("VimLeavePre", { | |
callback = function() | |
if not notify_server:is_closing() then | |
notify_server:close() | |
end | |
end, | |
}) | |
return notify_server | |
end | |
return { | |
start_server = notify_start_server, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment