mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local luaassert = require('luassert')
 | |
| 
 | |
| local M = {}
 | |
| 
 | |
| local SUBTBL = {
 | |
|   '\\000',
 | |
|   '\\001',
 | |
|   '\\002',
 | |
|   '\\003',
 | |
|   '\\004',
 | |
|   '\\005',
 | |
|   '\\006',
 | |
|   '\\007',
 | |
|   '\\008',
 | |
|   '\\t',
 | |
|   '\\n',
 | |
|   '\\011',
 | |
|   '\\012',
 | |
|   '\\r',
 | |
|   '\\014',
 | |
|   '\\015',
 | |
|   '\\016',
 | |
|   '\\017',
 | |
|   '\\018',
 | |
|   '\\019',
 | |
|   '\\020',
 | |
|   '\\021',
 | |
|   '\\022',
 | |
|   '\\023',
 | |
|   '\\024',
 | |
|   '\\025',
 | |
|   '\\026',
 | |
|   '\\027',
 | |
|   '\\028',
 | |
|   '\\029',
 | |
|   '\\030',
 | |
|   '\\031',
 | |
| }
 | |
| 
 | |
| --- @param v any
 | |
| --- @return string
 | |
| local function format_float(v)
 | |
|   -- On windows exponent appears to have three digits and not two
 | |
|   local ret = ('%.6e'):format(v)
 | |
|   local l, f, es, e = ret:match('^(%-?%d)%.(%d+)e([+%-])0*(%d%d+)$')
 | |
|   return l .. '.' .. f .. 'e' .. es .. e
 | |
| end
 | |
| 
 | |
| -- Formats Lua value `v`.
 | |
| --
 | |
| -- TODO(justinmk): redundant with vim.inspect() ?
 | |
| --
 | |
| -- "Nice table formatting similar to screen:snapshot_util()".
 | |
| -- Commit: 520c0b91a528
 | |
| function M.format_luav(v, indent, opts)
 | |
|   opts = opts or {}
 | |
|   local linesep = '\n'
 | |
|   local next_indent_arg = nil
 | |
|   local indent_shift = opts.indent_shift or '  '
 | |
|   local next_indent
 | |
|   local nl = '\n'
 | |
|   if indent == nil then
 | |
|     indent = ''
 | |
|     linesep = ''
 | |
|     next_indent = ''
 | |
|     nl = ' '
 | |
|   else
 | |
|     next_indent_arg = indent .. indent_shift
 | |
|     next_indent = indent .. indent_shift
 | |
|   end
 | |
|   local ret = ''
 | |
|   if type(v) == 'string' then
 | |
|     if opts.literal_strings then
 | |
|       ret = v
 | |
|     else
 | |
|       local quote = opts.dquote_strings and '"' or "'"
 | |
|       ret = quote
 | |
|         .. tostring(v)
 | |
|           :gsub(opts.dquote_strings and '["\\]' or "['\\]", '\\%0')
 | |
|           :gsub('[%z\1-\31]', function(match)
 | |
|             return SUBTBL[match:byte() + 1]
 | |
|           end)
 | |
|         .. quote
 | |
|     end
 | |
|   elseif type(v) == 'table' then
 | |
|     if v == vim.NIL then
 | |
|       ret = 'REMOVE_THIS'
 | |
|     else
 | |
|       local processed_keys = {}
 | |
|       ret = '{' .. linesep
 | |
|       local non_empty = false
 | |
|       local format_luav = M.format_luav
 | |
|       for i, subv in ipairs(v) do
 | |
|         ret = ('%s%s%s,%s'):format(ret, next_indent, format_luav(subv, next_indent_arg, opts), nl)
 | |
|         processed_keys[i] = true
 | |
|         non_empty = true
 | |
|       end
 | |
|       for k, subv in pairs(v) do
 | |
|         if not processed_keys[k] then
 | |
|           if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
 | |
|             ret = ret .. next_indent .. k .. ' = '
 | |
|           else
 | |
|             ret = ('%s%s[%s] = '):format(ret, next_indent, format_luav(k, nil, opts))
 | |
|           end
 | |
|           ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
 | |
|           non_empty = true
 | |
|         end
 | |
|       end
 | |
|       if nl == ' ' and non_empty then
 | |
|         ret = ret:sub(1, -3)
 | |
|       end
 | |
|       ret = ret .. indent .. '}'
 | |
|     end
 | |
|   elseif type(v) == 'number' then
 | |
|     if v % 1 == 0 then
 | |
|       ret = ('%d'):format(v)
 | |
|     else
 | |
|       ret = format_float(v)
 | |
|     end
 | |
|   elseif type(v) == 'nil' then
 | |
|     ret = 'nil'
 | |
|   elseif type(v) == 'boolean' then
 | |
|     ret = (v and 'true' or 'false')
 | |
|   else
 | |
|     print(type(v))
 | |
|     -- Not implemented yet
 | |
|     luaassert(false)
 | |
|   end
 | |
|   return ret
 | |
| end
 | |
| 
 | |
| -- Like Python repr(), "{!r}".format(s)
 | |
| --
 | |
| -- Commit: 520c0b91a528
 | |
| function M.format_string(fmt, ...)
 | |
|   local i = 0
 | |
|   local args = { ... }
 | |
|   local function getarg()
 | |
|     i = i + 1
 | |
|     return args[i]
 | |
|   end
 | |
|   local ret = fmt:gsub('%%[0-9*]*%.?[0-9*]*[cdEefgGiouXxqsr%%]', function(match)
 | |
|     local subfmt = match:gsub('%*', function()
 | |
|       return tostring(getarg())
 | |
|     end)
 | |
|     local arg = nil
 | |
|     if subfmt:sub(-1) ~= '%' then
 | |
|       arg = getarg()
 | |
|     end
 | |
|     if subfmt:sub(-1) == 'r' or subfmt:sub(-1) == 'q' then
 | |
|       -- %r is like built-in %q, but it is supposed to single-quote strings and
 | |
|       -- not double-quote them, and also work not only for strings.
 | |
|       -- Builtin %q is replaced here as it gives invalid and inconsistent with
 | |
|       -- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`,
 | |
|       -- lua leaves as-is.
 | |
|       arg = M.format_luav(arg, nil, { dquote_strings = (subfmt:sub(-1) == 'q') })
 | |
|       subfmt = subfmt:sub(1, -2) .. 's'
 | |
|     end
 | |
|     if subfmt == '%e' then
 | |
|       return format_float(arg)
 | |
|     else
 | |
|       return subfmt:format(arg)
 | |
|     end
 | |
|   end)
 | |
|   return ret
 | |
| end
 | |
| 
 | |
| return M
 | 
