Created
November 7, 2021 20:27
-
-
Save sunjon/ffc141f5e09a72134909b5b84f114a00 to your computer and use it in GitHub Desktop.
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
-- OSC 4 Color Parser for Neovim | |
-- Copyright Senghan Bright 2021 | |
local uv = vim.loop | |
-- check if COLORTERM is advertised by the terminal emulator | |
local colorterm = os.getenv("COLORTERM") | |
if not (colorterm == "truecolor") then | |
error("Truecolor environment not found. Ensure your terminal enables the 'COLORTERM' environment variable.") | |
end | |
if not vim.o.termguicolors then | |
error("`termguicolors` option is not set. 256 color mode only works for RGB UIs.") | |
end | |
-- Ascii decimal value lookup | |
local char = string.char | |
local ascii = { | |
BEL = char(7), | |
ESC = char(27), | |
NUM_FOUR = char(52), | |
BACKSLASH = char(92), | |
RBRACKET = char(93), | |
} | |
local OS_CMD_START = ascii.ESC .. ascii.RBRACKET .. ascii.NUM_FOUR | |
local OS_CMD_END = ascii.BACKSLASH .. ascii.BEL | |
-- | |
local function stty_cmd(fd, cmd) | |
local sys = vim.fn.system | |
local stty_bin = "stty" | |
local cmd_str = ("%s --file %s %s"):format(stty_bin, fd, cmd) | |
return sys(cmd_str) | |
end | |
local function parse_rgb_entries(data) | |
local rgb_pattern = "(%d+;rgb:%x+/%x+/%x+)" | |
local color_pattern = "%x%x(%x%x)" | |
local idx, rgb_str | |
local res = {} | |
for rgb_entry in data:gmatch(rgb_pattern) do | |
idx = rgb_entry:match ".-(%d+);" | |
rgb_str = "#" | |
for c in rgb_entry:gmatch(color_pattern) do | |
rgb_str = rgb_str .. c | |
end | |
res[idx] = rgb_str | |
end | |
return res | |
end | |
local function get_colors() | |
local nvim_pid = vim.fn.getpid() | |
local ppid = vim.api.nvim_get_proc(nvim_pid).ppid | |
local fd = ("/proc/%d/fd/0"):format(ppid) | |
-- save current mode settings and set raw mode | |
local orig_mode = stty_cmd(fd, "--save") | |
stty_cmd(fd, "raw -echo") | |
-- open connection to STTY file | |
local file_handle = assert(uv.fs_open(fd, "r+", 438)) | |
local TTY_BUF_READ_SIZE = 8192 | |
local chunk_size = 32 | |
local res = {} | |
local query, data, chunk_results | |
for j = 0, 255, chunk_size do | |
-- build query string | |
query = OS_CMD_START | |
for idx = j + 0, j + chunk_size do | |
query = query .. (";%d;?"):format(idx) | |
end | |
query = query .. OS_CMD_END | |
assert(uv.fs_write(file_handle, query)) | |
-- read response | |
data = assert(uv.fs_read(file_handle, TTY_BUF_READ_SIZE)) | |
chunk_results = parse_rgb_entries(data) | |
for i, r in pairs(chunk_results) do | |
res[i + 1] = r | |
end | |
end | |
-- restore original TTY mode | |
stty_cmd(fd, orig_mode) | |
return res | |
end | |
local terminal_colors = get_colors() | |
local term_color | |
for i, color in ipairs(terminal_colors) do | |
term_color = ("terminal_color_%d"):format(i-1) | |
vim.g[term_color] = color | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment