From 98e67a214c69aab91efe107b04d73ead29f9ef60 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 13 Jul 2024 21:59:34 +0800 Subject: [PATCH] feat(cpicker): add cmyk color space --- autoload/SpaceVim/layers/tools/cpicker.vim | 14 +- bundle/cpicker.nvim/lua/cpicker.lua | 2 +- .../cpicker.nvim/lua/cpicker/formats/cmyk.lua | 126 ++++++++++++++++++ .../cpicker.nvim/lua/cpicker/formats/hsl.lua | 8 +- .../cpicker.nvim/lua/cpicker/formats/hsv.lua | 7 +- .../cpicker.nvim/lua/cpicker/formats/rgb.lua | 63 +++++---- bundle/cpicker.nvim/lua/cpicker/util.lua | 2 +- .../cpicker.nvim/syntax/spacevim_cpicker.vim | 2 +- doc/SpaceVim.txt | 10 ++ docs/layers/tools/cpicker.md | 14 ++ lua/spacevim/api/color.lua | 60 +++++++-- 11 files changed, 259 insertions(+), 49 deletions(-) create mode 100644 bundle/cpicker.nvim/lua/cpicker/formats/cmyk.lua diff --git a/autoload/SpaceVim/layers/tools/cpicker.vim b/autoload/SpaceVim/layers/tools/cpicker.vim index 612820c98..312ef8dc6 100644 --- a/autoload/SpaceVim/layers/tools/cpicker.vim +++ b/autoload/SpaceVim/layers/tools/cpicker.vim @@ -17,6 +17,9 @@ " name = 'tools#cpicker' " < " +" @subsection layer options +" 1. default_spaces: set the default color spaces, the default value is `['rgb', 'hsl']` +" " @subsection Key bindings " > " Key Function @@ -34,6 +37,13 @@ " h/ reduce " l/ increase " < +" @subsection commands +" Instead of using key Binding, this layer also provides a Neovim command `:Cpicker` which can be used in cmdline. For example: +" > +" :Cpicker rgb cmyk +" < + +let s:default_spaces = ['rgb', 'hsl'] function! SpaceVim#layers#tools#cpicker#plugins() abort @@ -45,13 +55,13 @@ endfunction function! SpaceVim#layers#tools#cpicker#config() abort - call SpaceVim#mapping#space#def('nnoremap', ['i', 'p', 'c'], 'Cpicker all', + call SpaceVim#mapping#space#def('nnoremap', ['i', 'p', 'c'], 'Cpicker ' . join(s:default_spaces, ' '), \ 'insert-color-with-picker', 1) endfunction function! SpaceVim#layers#tools#cpicker#set_variable(var) abort - let g:cpicker_default_format = get(a:var, 'default_format', 'hex') + let s:default_spaces = get(a:var, 'default_spaces', s:default_spaces) endfunction function! SpaceVim#layers#tools#cpicker#loadeable() abort diff --git a/bundle/cpicker.nvim/lua/cpicker.lua b/bundle/cpicker.nvim/lua/cpicker.lua index 413f54bf3..e236d1f5a 100644 --- a/bundle/cpicker.nvim/lua/cpicker.lua +++ b/bundle/cpicker.nvim/lua/cpicker.lua @@ -74,7 +74,7 @@ end local function copy_color() local from, to = vim - .regex([[#[0123456789ABCDEF]\+\|rgb(\d\+,\s\d\+,\s\d\+)\|hsl(\d\+,\s\d\+%,\s\d\+%)\|hsv(\d\+,\s\d\+%,\s\d\+%)]]) + .regex([[#[0123456789ABCDEF]\+\|rgb(\d\+,\s\d\+,\s\d\+)\|hsl(\d\+,\s\d\+%,\s\d\+%)\|hsv(\d\+,\s\d\+%,\s\d\+%)\|cmyk(\d\+%,\s\d\+%,\s\d\+%,\s\d\+%)]]) :match_str(vim.fn.getline('.')) if from then vim.fn.setreg('+', string.sub(vim.fn.getline('.'), from, to + 1)) diff --git a/bundle/cpicker.nvim/lua/cpicker/formats/cmyk.lua b/bundle/cpicker.nvim/lua/cpicker/formats/cmyk.lua new file mode 100644 index 000000000..bcb1d99bc --- /dev/null +++ b/bundle/cpicker.nvim/lua/cpicker/formats/cmyk.lua @@ -0,0 +1,126 @@ +--============================================================================= +-- cmyk.lua --- +-- Copyright (c) 2019-2024 Wang Shidong & Contributors +-- Author: Wang Shidong < wsdjeg@outlook.com > +-- URL: https://spacevim.org +-- License: GPLv3 +--============================================================================= +local M = {} + +local color = require('spacevim.api.color') +local util = require('cpicker.util') + +local cyan = 0 +local magenta = 0 +local yellow = 0 +local black = 0 + +local function on_change_argv() + return 'cmyk', { cyan, magenta, yellow, black } +end + +function M.buf_text() + local rst = {} + local c_bar = util.generate_bar(cyan, '+') + local m_bar = util.generate_bar(magenta, '+') + local y_bar = util.generate_bar(yellow, '+') + local k_bar = util.generate_bar(black, '+') + table.insert(rst, 'CMYK: C: ' .. string.format('%4s', math.floor(cyan * 100 + 0.5)) .. ' ' .. c_bar) + table.insert(rst, ' M: ' .. string.format('%4s', math.floor(magenta * 100 + 0.5)) .. ' ' .. m_bar) + table.insert(rst, ' Y: ' .. string.format('%4s', math.floor(yellow * 100 + 0.5)) .. ' ' .. y_bar) + table.insert(rst, ' K: ' .. string.format('%4s', math.floor(black * 100 + 0.5)) .. ' ' .. k_bar) + return rst +end + +function M.color_code() + return + ' =========' .. string.format( + ' cmyk(%s%%, %s%%, %s%%, %s%%)', + math.floor(cyan * 100 + 0.5), + math.floor(magenta * 100 + 0.5), + math.floor(yellow * 100 + 0.5), + math.floor(black * 100 + 0.5) + ) +end + +local function increase_cyan() + if cyan <= 0.99 then + cyan = cyan + 0.01 + elseif cyan < 1 then + cyan = 1 + end + return on_change_argv() +end +local function reduce_cyan() + if cyan > 0.01 then + cyan = cyan - 0.01 + elseif cyan > 0 then + cyan = 0 + end + return on_change_argv() +end +local function increase_magenta() + if magenta <= 0.99 then + magenta = magenta + 0.01 + elseif magenta < 1 then + magenta = 1 + end + return on_change_argv() +end +local function reduce_magenta() + if magenta > 0.01 then + magenta = magenta - 0.01 + elseif magenta > 0 then + magenta = 0 + end + return on_change_argv() +end +local function increase_yellow() + if yellow <= 0.99 then + yellow = yellow + 0.01 + elseif yellow < 1 then + yellow = 1 + end + return on_change_argv() +end +local function reduce_yellow() + if yellow > 0.01 then + yellow = yellow - 0.01 + elseif yellow > 0 then + yellow = 0 + end + return on_change_argv() +end +local function increase_black() + if black <= 0.99 then + black = black + 0.01 + elseif black < 1 then + black = 1 + end + return on_change_argv() +end +local function reduce_black() + if black > 0.01 then + black = black - 0.01 + elseif black > 0 then + black = 0 + end + return on_change_argv() +end +function M.increase_reduce_functions() + return { + { increase_cyan, reduce_cyan }, + { increase_magenta, reduce_magenta }, + { increase_yellow, reduce_yellow }, + { increase_black, reduce_black }, + } +end + +function M.on_change(f, code) + if f == 'cmyk' then + return + end + cyan, magenta, yellow, black = color[f .. '2cmyk'](unpack(code)) +end + +return M diff --git a/bundle/cpicker.nvim/lua/cpicker/formats/hsl.lua b/bundle/cpicker.nvim/lua/cpicker/formats/hsl.lua index af38f6ce4..d727b47a3 100644 --- a/bundle/cpicker.nvim/lua/cpicker/formats/hsl.lua +++ b/bundle/cpicker.nvim/lua/cpicker/formats/hsl.lua @@ -21,8 +21,8 @@ end function M.buf_text() local rst = {} local h_bar = util.generate_bar(hue, '+', 360) - local s_bar = util.generate_bar(saturation, '+', 1) - local l_bar = util.generate_bar(lightness, '+', 1) + local s_bar = util.generate_bar(saturation, '+') + local l_bar = util.generate_bar(lightness, '+') table.insert(rst, 'HSL: H: ' .. string.format('%4s', math.floor(hue + 0.5)) .. ' ' .. h_bar) table.insert( rst, @@ -46,8 +46,10 @@ function M.color_code() end local function increase_hsl_h() - if hue < 360 then + if hue <= 359 then hue = hue + 1 + elseif hue < 360 then + hue = 360 end return on_change_argv() end diff --git a/bundle/cpicker.nvim/lua/cpicker/formats/hsv.lua b/bundle/cpicker.nvim/lua/cpicker/formats/hsv.lua index ce0786eaa..258d0ada5 100644 --- a/bundle/cpicker.nvim/lua/cpicker/formats/hsv.lua +++ b/bundle/cpicker.nvim/lua/cpicker/formats/hsv.lua @@ -22,8 +22,8 @@ function M.buf_text() local rst = {} local h_bar = util.generate_bar(hue, '+', 360) - local s_bar = util.generate_bar(saturation, '+', 1) - local l_bar = util.generate_bar(value, '+', 1) + local s_bar = util.generate_bar(saturation, '+') + local l_bar = util.generate_bar(value, '+') table.insert(rst, 'HSV: H: ' .. string.format('%4s', math.floor(hue + 0.5)) .. ' ' .. h_bar) table.insert( rst, @@ -47,8 +47,9 @@ function M.color_code() end local function increase_hsl_h() - if hue < 360 then + if hue <= 359 then hue = hue + 1 + elseif hue < 360 then hue = 360 end return on_change_argv() end diff --git a/bundle/cpicker.nvim/lua/cpicker/formats/rgb.lua b/bundle/cpicker.nvim/lua/cpicker/formats/rgb.lua index 7856951fe..d75403477 100644 --- a/bundle/cpicker.nvim/lua/cpicker/formats/rgb.lua +++ b/bundle/cpicker.nvim/lua/cpicker/formats/rgb.lua @@ -10,9 +10,9 @@ local M = {} local color = require('spacevim.api.color') local util = require('cpicker.util') -local red = 0 -- [0, 255] -local green = 0 -- [0, 255] -local blue = 0 -- [0, 255] +local red = 0 -- [0, 1] +local green = 0 -- [0, 1] +local blue = 0 -- [0, 1] local function on_change_argv() return 'rgb', { red, green, blue } @@ -23,9 +23,18 @@ function M.buf_text() local r_bar = util.generate_bar(red, '+') local g_bar = util.generate_bar(green, '+') local b_bar = util.generate_bar(blue, '+') - table.insert(rst, 'RGB: R: ' .. string.format('%4s', red) .. ' ' .. r_bar) - table.insert(rst, ' G: ' .. string.format('%4s', green) .. ' ' .. g_bar) - table.insert(rst, ' B: ' .. string.format('%4s', blue) .. ' ' .. b_bar) + table.insert( + rst, + 'RGB: R: ' .. string.format('%4s', math.floor(red * 255 + 0.5)) .. ' ' .. r_bar + ) + table.insert( + rst, + ' G: ' .. string.format('%4s', math.floor(green * 255 + 0.5)) .. ' ' .. g_bar + ) + table.insert( + rst, + ' B: ' .. string.format('%4s', math.floor(blue * 255 + 0.5)) .. ' ' .. b_bar + ) return rst end @@ -33,42 +42,48 @@ function M.color_code() return ' =========' .. ' ' .. color.rgb2hex(red, green, blue) end -local function increase_rgb_red() - if red < 255 then - red = red + 1 +local function increase(c) + if c <= 1 - 1 / 255 then + c = c + 1 / 255 + elseif c < 1 then + c = 1 end + return c +end + +local function reduce(c) + if c >= 1 / 255 then + c = c - 1 / 255 + elseif c > 0 then + c = 0 + end + return c +end + +local function increase_rgb_red() + red = increase(red) return on_change_argv() end local function reduce_rgb_red() - if red > 0 then - red = red - 1 - end + red = reduce(red) return on_change_argv() end local function increase_rgb_green() - if green < 255 then - green = green + 1 - end + green = increase(green) return on_change_argv() end local function reduce_rgb_green() - if green > 0 then - green = green - 1 - end + green = reduce(green) return on_change_argv() end local function increase_rgb_blue() - if blue < 255 then - blue = blue + 1 - end + blue = increase(blue) return on_change_argv() end local function reduce_rgb_blue() - if blue > 0 then - blue = blue - 1 - end + blue = reduce(blue) return on_change_argv() end function M.increase_reduce_functions() diff --git a/bundle/cpicker.nvim/lua/cpicker/util.lua b/bundle/cpicker.nvim/lua/cpicker/util.lua index 1a03fb06e..661c58444 100644 --- a/bundle/cpicker.nvim/lua/cpicker/util.lua +++ b/bundle/cpicker.nvim/lua/cpicker/util.lua @@ -12,7 +12,7 @@ local M = {} local color = require('spacevim.api.color') function M.generate_bar(n, char, m) - return string.rep(char, math.floor(24 * n / (m or 255))) + return string.rep(char, math.floor(24 * n / (m or 1))) end function M.get_hex_code(t, code) diff --git a/bundle/cpicker.nvim/syntax/spacevim_cpicker.vim b/bundle/cpicker.nvim/syntax/spacevim_cpicker.vim index c172ca18a..015ae2545 100644 --- a/bundle/cpicker.nvim/syntax/spacevim_cpicker.vim +++ b/bundle/cpicker.nvim/syntax/spacevim_cpicker.vim @@ -5,7 +5,7 @@ let b:current_syntax = 'spacevim_cpicker' syntax case ignore syn match ProcessBar /[?=+]\+/ -syn match SpaceVimPickerCode /#[0123456789ABCDEF]\+\|rgb(\d\+,\s\d\+,\s\d\+)\|hsl(\d\+,\s\d\+%,\s\d\+%)\|hsv(\d\+,\s\d\+%,\s\d\+%)/ +syn match SpaceVimPickerCode /#[0123456789ABCDEF]\+\|rgb(\d\+,\s\d\+,\s\d\+)\|hsl(\d\+,\s\d\+%,\s\d\+%)\|hsv(\d\+,\s\d\+%,\s\d\+%)\|cmyk(\d\+%,\s\d\+%,\s\d\+%,\s\d\+%)/ syn match SpaceVimPickerBackground /=\+/ highlight ProcessBar ctermfg=Gray ctermbg=Gray guifg=Gray guibg=Gray diff --git a/doc/SpaceVim.txt b/doc/SpaceVim.txt index 4c356b115..6c0b6f801 100644 --- a/doc/SpaceVim.txt +++ b/doc/SpaceVim.txt @@ -6302,6 +6302,10 @@ configuration file. name = 'tools#cpicker' < +LAYER OPTIONS + 1. default_spaces: set the default color spaces, the default value is + `['rgb', 'hsl']` + KEY BINDINGS > @@ -6320,6 +6324,12 @@ Key bindings in cpicker: h/ reduce l/ increase < +COMMANDS +Instead of using key Binding, this layer also provides a Neovim command +`:Cpicker` which can be used in cmdline. For example: +> + :Cpicker rgb cmyk +< ============================================================================== TOOLS#DASH *SpaceVim-layers-tools-dash* diff --git a/docs/layers/tools/cpicker.md b/docs/layers/tools/cpicker.md index 9bf196313..3ba1dec5e 100644 --- a/docs/layers/tools/cpicker.md +++ b/docs/layers/tools/cpicker.md @@ -9,7 +9,9 @@ description: "This layer provides color picker for SpaceVim" - [Description](#description) - [Install](#install) +- [Layer options](#layer-options) - [Key bindings](#key-bindings) +- [Commands](#commands) @@ -26,8 +28,20 @@ To use this configuration layer, add it to your `~/.SpaceVim.d/init.toml`. name = "tools#cpicker" ``` +## Layer options + +1. default_spaces: set the default color spaces, the default value is `['rgb', 'hsl']`. Available spaces: rgb, hsl, hsv, cmyk. + ## Key bindings | Key Binding | Description | | ----------- | ----------------- | | `SPC i p c` | open color picker | + +## Commands + +Instead of using key Binding, this layer also provides a Neovim command `:Cpicker` which can be used in cmdline. For example: + +``` +:Cpicker rgb cmyk +``` diff --git a/lua/spacevim/api/color.lua b/lua/spacevim/api/color.lua index c6dd58c2b..d68e7b94c 100644 --- a/lua/spacevim/api/color.lua +++ b/lua/spacevim/api/color.lua @@ -11,9 +11,6 @@ local color = {} -- 参考: https://blog.csdn.net/Sunshine_in_Moon/article/details/45131285 color.rgb2hsl = function(r, g, b) - r = r / 255 - g = g / 255 - b = b / 255 local max = math.max(r, g, b) local min = math.min(r, g, b) local h, s, l @@ -39,7 +36,7 @@ color.rgb2hsl = function(r, g, b) s = (max - min) / (2 - 2 * l) end - return math.floor(h), s, l + return h, s, l end -- https://stackoverflow.com/questions/68317097/how-to-properly-convert-hsl-colors-to-rgb-colors-in-lua @@ -78,16 +75,35 @@ color.hsl2rgb = function(h, s, l) b = hue2rgb(p, q, h - 1 / 3) end - return math.floor(r * 255 + 0.5), math.floor(g * 255 + 0.5), math.floor(b * 255 + 0.5) + return r, g, b +end + +-- https://www.rapidtables.com/convert/color/rgb-to-cmyk.html + +color.rgb2cmyk = function(r, g, b) + local c, m, y, k + k = 1 - math.max(r, g, b) + if k ~= 1 then + c = (1 - r - k) / (1 - k) + m = (1 - g - k) / (1 - k) + y = (1 - b - k) / (1 - k) + else + c, m, y = 0, 0, 0 + end + return c, m, y, k +end + +color.cmyk2rgb = function(c, m, y, k) + local r, g, b + r = (1 - c) * (1 - k) + g = (1 - m) * (1 - k) + b = (1 - y) * (1 - k) + return r, g, b end -- https://www.rapidtables.com/convert/color/rgb-to-hsv.html color.rgb2hsv = function(r, g, b) - r = r / 255 - g = g / 255 - b = b / 255 - local cmax = math.max(r, g, b) local cmin = math.min(r, g, b) local d = cmax - cmin @@ -112,7 +128,7 @@ color.rgb2hsv = function(r, g, b) v = cmax - return math.floor(h), s, v + return h, s, v end -- https://www.rapidtables.com/convert/color/hsv-to-rgb.html @@ -136,7 +152,7 @@ color.hsv2rgb = function(h, s, v) r, g, b = c, 0, x end r, g, b = (r + m), (g + m), (b + m) - return math.floor(r * 255 + 0.5), math.floor(g * 255 + 0.5), math.floor(b * 255 + 0.5) + return r, g, b end color.hsv2hsl = function(h, s, v) return color.rgb2hsl(color.hsv2rgb(h, s, v)) @@ -144,6 +160,19 @@ end color.hsl2hsv = function(h, s, l) return color.rgb2hsv(color.hsl2rgb(h, s, l)) end +color.hsl2cmyk = function (h, s, l) + return color.rgb2cmyk(color.hsl2rgb(h, s, l)) +end +color.hsv2cmyk = function (h, s, v) + return color.rgb2cmyk(color.hsv2rgb(h, s, v)) +end +color.cmyk2hsv = function(c, m, y, k) + return color.rgb2hsv(color.cmyk2rgb(c, m, y, k)) +end + +color.cmyk2hsl = function(c, m, y, k) + return color.rgb2hsl(color.cmyk2rgb(c, m, y, k)) +end local function decimalToHex(decimal) local hex = '' @@ -162,9 +191,9 @@ local function decimalToHex(decimal) end end color.rgb2hex = function(r, g, b) - r = decimalToHex(r) - g = decimalToHex(g) - b = decimalToHex(b) + r = decimalToHex(math.floor(r * 255 + 0.5)) + g = decimalToHex(math.floor(g * 255 + 0.5)) + b = decimalToHex(math.floor(b * 255 + 0.5)) return '#' .. r .. g .. b end color.hsv2hex = function(h, s, v) @@ -173,5 +202,8 @@ end color.hsl2hex = function(h, s, l) return color.rgb2hex(color.hsl2rgb(h, s, l)) end +color.cmyk2hex = function(c, y, m, k) + return color.rgb2hex(color.cmyk2rgb(c, y, m, k)) +end return color