A collection of useful Lua utilities for Neovim, extracted from SpaceVim.
Features
- Color manipulation — Comprehensive color space conversions (RGB, HSL, HSV, CMYK, HWB, HEX, Linear, XYZ, Lab, LCH)
- Data structures — Dictionary, list, string, and TOML parsing utilities
- File operations — Filetype icons, path unification, file read/write, file/directory finding
- Highlight — Syntax group manipulation, separator highlighting, syntax inspection at cursor
- Interactive UI — Command-line prompt and menu system
- Vim/Neovim compatibility — Cross-platform API layer for Vim and Neovim
- Regex — Perl-style regex to Vim regex converter
- System detection — OS detection (Linux, Windows, macOS, Cygwin)
- Unicode — Spinner animations, messletters (circled letters/numbers, bubble numbers)
- Misc — Password generation, time formatting, language aliases, buffer/window management
Installation
Using nvim-plug
require('plug').add({ { 'wsdjeg/utils.nvim' } })
Then run :PlugInstall utils.nvim.
Using luarocks
luarocks install utils.nvim
Using lazy.nvim
{
'wsdjeg/utils.nvim',
}Modules
utils.color
Full color space conversion library. All values use the [0, 1] range (except HSL/HSV hue in degrees and CMYK in [0, 1]).
local color = require('utils.color') -- RGB <-> HSL local h, s, l = color.rgb2hsl(0.2, 0.4, 0.6) local r, g, b = color.hsl2rgb(210, 0.5, 0.5) -- RGB <-> HEX local hex = color.rgb2hex(0.2, 0.4, 0.6) -- "#336699" local r, g, b = color.hex2rgb('#336699') -- RGB <-> HSV local h, s, v = color.rgb2hsv(0.2, 0.4, 0.6) -- RGB <-> CMYK local c, m, y, k = color.rgb2cmyk(0.2, 0.4, 0.6) -- RGB <-> HWB local h, w, b = color.rgb2hwb(0.2, 0.4, 0.6) -- RGB <-> Lab local L, a, b = color.rgb2lab(0.2, 0.4, 0.6) -- Lab <-> LCH local L, C, H = color.lab2lch(50, 20, -10)
Supported conversions: RGB, HSL, HSV, CMYK, HWB, HEX, Linear RGB, XYZ, Lab, LCH — all interchangeable.
utils.data.string
String manipulation utilities.
local str = require('utils.data.string') str.trim(' hello ') -- 'hello' str.trim_start(' hello') -- 'hello' str.trim_end('hello ') -- 'hello' str.fill('hi', 10) -- 'hi ' str.fill_left('hi', 10) -- ' hi' str.toggle_case('Hello') -- 'hELLO' str.string2chars('abc') -- {'a', 'b', 'c'} str.strcharpart('hello', 2, 4) -- 'll'
utils.data.toml
TOML parser.
local toml = require('utils.data.toml') local data = toml.parse([[ title = "TOML Example" [owner] name = "Tom Preston-Werner" ]]) -- data.title == "TOML Example" -- data.owner.name == "Tom Preston-Werner" -- Or parse from file local data = toml.parse_file('config.toml')
utils.data.dict
Dictionary utilities.
local dict = require('utils.data.dict') local d = dict.make({'a', 'b', 'c'}, {1, 2, 3}) -- { a = 1, b = 2, c = 3 }
utils.data.list
List utilities.
local list = require('utils.data.list') local v = list.pop({1, 2, 3}) -- 3 (removes and returns last element)
utils.file
File and path utilities.
local file = require('utils.file') -- Get filetype icon local icon = file.fticon('main.lua') -- '' -- Path operations local path = file.unify_path('./src/../lib') -- normalized path local fname = file.path_to_fname('/a/b/c.lua') -- '_a_b_c_lua' -- File read/write local lines = file.read('output.log') file.write('new line', 'output.log') -- append file.override('content', 'output.log') -- overwrite -- Find files/directories local f = file.findfile('Makefile', '.') local d = file.finddir('src', '.')
utils.highlight
Highlight group manipulation.
local hi = require('utils.highlight') -- Get highlight group as dictionary local group = hi.group2dict('Error') -- Set highlight hi.hi({ name = 'MyHighlight', guifg = '#ff0000', guibg = '#000000', bold = 1, }) -- Create separator highlights between two groups hi.hi_separator('Normal', 'StatusLine') -- Get syntax at cursor position (supports Treesitter & semantic tokens) local name, hl = hi.syntax_at()
utils.prompt
Interactive command-line prompt with cursor support.
local prompt = require('utils.prompt') prompt._prompt.mpt = 'input ==> ' prompt._handle_fly = function(input) print('User typed: ' .. input) end prompt._onclose = function() print('Prompt closed') end prompt.open()
utils.cmdlinemenu
Interactive command-line menu.
local menu = require('utils.cmdlinemenu') menu.menu({ {'Option 1', function() print('Selected 1') end}, {'Option 2', 'echo "Selected 2"'}, {'Option 3', function() print('Selected 3') end}, })
utils.vim.argv
Command-line argument parser.
local argv = require('utils.vim.argv') local args = argv.parser('git commit -m "hello world"') -- {'git', 'commit', '-m', 'hello world'}
utils.vim.buffer
Buffer operations.
local buf = require('utils.vim.buffer') local bufnr = buf.create_buf(false, true) -- create scratch buffer buf.set_option(bufnr, 'buflisted', true) local listed = buf.listed_buffers() buf.open_pos('edit', 'file.lua', 10, 1) -- open at line 10, col 1
utils.vim.keys
Key code utilities.
local Key = require('utils.vim.keys') local esc = Key.t('<Esc>') -- terminal escape code for <Esc> local name = Key.nr2name(32) -- 'SPC' local name = Key.char2name('<CR>') -- '<CR>'
utils.vim.regex
Convert Perl-style regex to Vim regex.
local regex = require('utils.vim.regex') local vim_pattern = regex.parser('\\bword\\b', true) -- Result: '\v<word>'
utils.vim.compatible
Compatibility layer between Vim and Neovim.
local cmp = require('utils.vim.compatible') cmp.has('nvim-0.10.0') -- 1 or 0 cmp.echo('Hello') cmp.islist({1, 2, 3}) -- true
utils.vim.option
Set local buffer/window options (requires Neovim 0.8.0+).
local opt = require('utils.vim.option') opt.setlocalopt(bufnr, winid, { number = true, wrap = false, })
utils.vim.statusline
Statusline builder with floating window support.
local sl = require('utils.vim.statusline') -- Build a statusline string local line = sl.build( {'mode'}, {'file'}, '|', '|', 'filename', 'tag', 'StatusLine', 'StatusLineNC', 'StatusLineC', 'StatusLineZ', 80 ) -- Or show in a floating window sl.open_float({{'Mode: NORMAL', 'Normal'}})
utils.vim.window
Window utilities.
local win = require('utils.vim.window') win.is_float(winid) -- check if window is floating win.is_last_win() -- check if last non-floating window
utils.system
Operating system detection.
local sys = require('utils.system') sys.isWindows -- 1 or 0 sys.isLinux -- 1 or 0 sys.isOSX -- 1 or 0 sys.name() -- 'linux', 'windows', 'mac', or 'cygwin' sys.isDarwin() -- 1 or 0 sys.fileformat() -- OS icon
utils.password
Password generator.
local pwd = require('utils.password') pwd.generate_simple(16) -- random 16-character alphanumeric string
utils.time
Time utilities.
local time = require('utils.time') time.current_time() -- "02:30 PM" time.current_date() -- "Mon Jan 15"
utils.language
Filetype name aliases.
local lang = require('utils.language') lang.get_alias('typescript') -- 'TypeScript' lang.get_alias('python') -- 'Python' lang.get_alias('typescriptreact') -- 'TypeScript React'
utils.messletters
Unicode symbol utilities.
local ml = require('utils.messletters') ml.circled_letter('A') -- 'Ⓐ' ml.circled_num(1, 0) -- '①' ml.bubble_num(1, 0) -- '➊' ml.index_num(2) -- '²' ml.parenthesized_num(1) -- '⑴' ml.num_period(1) -- '⒈'
utils.unicode.spinners
Terminal spinner animations.
local spinners = require('utils.unicode.spinners') local s = spinners:new(function(icon) vim.api.nvim_echo({{icon, 'Normal'}}, false, {}) end) s:start() -- start animation -- ... s:stop() -- stop animation