搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

栏目: C++ · 发布时间: 4年前

内容简介:最近 vscode 在技术圈火了一阵子,每天都可以在掘金上看到安利文章和奇葩的插件,什么"杨超越鼓励师",还有上班摸鱼系列,"看小说插件","看股票插件",让我越发觉得 vscode 的功能越来越强大,强大到可以做任何事情,就像操作系统,而这有没有很像神之编辑器 emacs。最近台湾 emacs 圈中出了一个叛徒,最后这个维护人叛逃到 vscode 阵营并将这一消息发布到了台湾官方 emacs 推特。编辑器之争,在语言还在蓬勃发展的今天仍在持续,Vim 和 Emacs 谁是最好的编辑器,在程序员的圈子里是一

最近 vscode 在技术圈火了一阵子,每天都可以在掘金上看到安利文章和奇葩的插件,什么"杨超越鼓励师",还有上班摸鱼系列,"看小说插件","看股票插件",让我越发觉得 vscode 的功能越来越强大,强大到可以做任何事情,就像操作系统,而这有没有很像神之编辑器 emacs。最近台湾 emacs 圈中出了一个叛徒,最后这个维护人叛逃到 vscode 阵营并将这一消息发布到了台湾官方 emacs 推特。

编辑器之争,在语言还在蓬勃发展的今天仍在持续,Vim 和 Emacs 谁是最好的编辑器,在 程序员 的圈子里是一个经久不衰的话题,不论在哪个地方都能轻而易举的引起一场圣战。在公司里使用的开发语言主要是 C++ 和 python,小组同事使用的开发环境也是各种各样,有 NetBean,vscode,C++ eclipse,pycharm 以及 vim。 编辑器或 IDE 始终都只是工具,工具的价值不是看它功能有多强大,有多丰富,要看它能给我们产生多少价值 ,所以同个 工具 的价值没办法放在不同的人上去比较。我的观点是如果你在开发过程中会经常使用两到三个语言,开发过程中习惯的衔接很重要,我会推荐使用 vim;但是IDE是一个经过高度封装的工具,它对开发流程,开发方式等有一定的假设,所以在很多时候特别是实际项目中,也会为我们节约了大量宝贵的时间。

每种 IDE 都有自己的配置和使用习惯,数量一多,切换来切换去学习成本也很高。除了 vim,平时我也会在 windows 下使用 sublime 看看代码,因为轻快且在 windows 下可以快速编辑剪切复制。用过 pycharm 开发过 python,用过一段时间 eclipse 进行 C++ 开发,结合 beyond compare 方便把 windows 下代码同步到远程 linux 上,然后再进行 make 编译,但最后都统一切到了 vim。

说说我选择 vim 作为主力开发环境的原因,IDE 很多,学习成本一样很高,使用 N 种语言就可能会有 N 种 IDE。IDE 有它自己的好处,它已经针对某种语言进行集成优化,用户需要配置的东西其实不会很多。但其实越高度固化的东西可能越不好用,缺少一定的灵活性。vim 插件多,支持各种语言,同时也解决了 linux 同步运行问题,著名的插件在 github 和 stackoverflow 都很活跃,一个 vim 解决所有 ide。

我使用的 vim 进行 python 和 C++ 进行后台开发,最主要的功能还是不能没有, 提示补全,定义跳转,关键词搜索,语法高亮,语法检查,缩进折叠,函数展示大纲,文件模板,目录树等等 ,而我的 vim 现在也可以方便完成这些功能。

下面开始说说 2019,我使用的 vim 插件,主要是简单的介绍,每一个我都会简单介绍插件和使用操作,以及最重要的文档,因为里面有更详细的使用信息。

学习资源

在 github 上有一个不错的 vim 学习资源,从最简单的介绍起:

Vim 从入门到精通: github.com/wsdjeg/vim-… 笨方法学 vimscriptwww.treelib.com/book-detail…

另外,很多 vim 插件我还在知乎上关注一些 Vimer,比如:

  1. 韦易笑 ( www.zhihu.com/people/skyw… )
  2. 赵启明 ( www.zhihu.com/people/zhao… )
  3. Vim专栏 ( zhuanlan.zhihu.com/hack-vim )

一般都会介绍如何搭建 Vim IDE 和插件。

另外,我还喜欢在 github 上通过查找 vim 相关的插件,按照 Most Star 降序浏览。

我的 .vimrc 参考: github.com/cposture/my…

插件管理

插件

vim 8 已经支持 异步执行 功能了,并且在大多数插件中得到了支持,异步插件管理器,比如 plug.vim,在更新插件再也不用等那么久了,不再推荐老牌的 vundle。

vim-plug 不仅支持异步更新功能,还 支持针对文件类型和启动命令的延迟加载功能 ,让 vim 的启动速度再提高很多。

搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

文档

  1. 安装和使用参考: blog.jobbole.com/114132/
  2. 延迟加载插件的技术: segmentfault.com/a/119000001…
  3. vim 启动速度慢分析: segmentfault.com/a/119000001…

配置

延迟加载插件

plug.vim 支持插件延迟加载,不至于不相关的插件一开始都启动;plug.vim 支持按命令(command)或文件类型(file_type)这两种配置。

" 在第一次执行 NERDTreeToggle 命令时,NERD tree 插件才开始加载
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
" on 支持多命令
Plug 'junegunn/vim-github-dashboard', { 'on': ['GHDashboard', 'GHActivity'] }
" 打开 clojure 类型的文件时,vim-fireplace' 才开始加载
Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" for 支持多文件类型
Plug 'kovisoft/paredit', { 'for': ['clojure', 'scheme'] }
复制代码

使用 on 延迟加载 YouCompleteMe 方法:

  1. 先把 on 命令列表置空,默认不启动
  2. 我们使用自动命令,可以让Vim自动执行指定的命令,指定的命令会在指定事件发生的时候执行;进入 insert 模式时,手动调用 call plug#load('YouCompleteMe')
  3. 删除自动命令组
# on 为空,后面手动加载
Plug '~/YouCompleteMe', {'on': []}
augroup load_ycm
    autocmd!
    "延迟加载,在 insert 模式手动加载插件
    autocmd InsertEnter * call plug#load('YouCompleteMe') | autocmd! load_ycm
augroup END
复制代码

延迟加载不是银弹,最终要看是不是有这个需求;所以我们一般在出现启动比较慢的情况下才去尝试使用延迟加载。另外,一般插件的作者都要考虑本身延迟加载功能,而不是依靠等待外部插件去实现延迟加载。

那么如何启动速度慢的情况下分析插件问题呢?

vim 启动时可以指定选项, vim --startuptime vim.log -c q ,启动时把计时信息写入文件,用于分析载入 .vimrc、插件和打开首个文件的过程中时哪一步最耗时。

times in msec
 clock self+sourced self: sourced script
 clock elapsed: other lines
...
003.691 002.008 002.008: sourcing /home/luffichen/.vim/autoload/plug.vim
021.676 000.021 000.021: sourcing /usr/local/share/vim/vim81/filetype.vim
021.869 000.017 000.017: sourcing /usr/local/share/vim/vim81/filetype.vim
...
复制代码

其中第一列是时间点,第二列和第三列都是时长(区别:第二个是self+sourced,第三个是self),我们主要关注第三列,脚本本身的执行时间。

因为同一个插件会有多行数据,我们要手动把同一插件的第三列统计一个总和,这样很繁琐,所以 github 上有人写了一个插件,专门用于分析每个插件的执行耗时,并输出直线图,具体可以看看: github.com/hyiltiz/vim…

搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

还有其他分析方法,具体可见: VIM加速: segmentfault.com/a/119000001…

简明操作

:PlugInstall
:PlugStatus
:PlugClean

离线安装插件

因为公司的 Linux 开发环境一般无法连接到外网,所以不能直接使用 plug 从 github 上安装插件,我的方法是:

以 auto-pairs 为例,

  1. 在可以访问外网的环境, git clone https://github.com/jiangmiao/auto-pairs
  2. 打包压缩 auto-pairs.zip
  3. 上传压缩包到服务器,并解压, rz -byeunzip auto-pairs.zip
  4. 统一拷贝到自定义的插件目录,我这里都放在目录 ~/vim-plugin 下, cp -rf auto-pairs ~/vim-plugin/
  5. 配置 .vimrc,指定插件的本地目录, Plug '~/vim-plugin/auto-pairs'
  6. 运行 vim,并执行 :PlugInstall
  7. 查看安装情况, :PlugStatus

提示补全

插件

这几个插件完美的解决了 C++ 和 python 的代码补全和提示,其他语言可以参考其他的介绍。

随着 vscode lsp 协议的推广,vim 语法补全也出现了相应的插件,比如 coc.nvim ,主要是异步并且支持很多 vscode 上的语法补全插件,可以试用一下(ps:公司的系统版本比较老并且网络不通,所以一直没去折腾这插件,后面听说出现了一个打包版本,可以不用安装,后面有需求可以试用一下)。

coc.nvim 具体的介绍: zhuanlan.zhihu.com/p/39302327 coc.nvim: github.com/neoclide/co…

目前,C/C++ 的补全的话,请直接使用YouCompleteMe,没有之一;另外 YCM-Generator 主要用于解决 YouCompleteMe 配置文件生成麻烦问题。

本来最新版本的 YCM 也支持 python 的补全,只要安装一个 jedi 就可以了,但是公司开发环境系统版本不是很高,编译不了最新版本的 YCM,所以安装一个以后端 jedi 为补全客户端的插件 jedi-vim

本来还想介绍一下 SuperTab( github.com/ervandew/su… ),它实现的功能简单的说就是用 tab 来调用 vim 的补全功能,这和 linux 操作习惯完全一致,并且方便而合理,但是 YCM 本身就包含了 SuperTab 的功能,所以不再多余的安装 SuperTab 插件了,以免冲突。另外 YCM 文档还说了包含其他插件的功能,具体如下:

clang_complete
AutoComplPop
Supertab
neocomplcache
复制代码

最后补充下 omnicomple,有时 YCM 和 jedi-vim 没办法在某些情况下进行补全,比如我经常遇到,我只想补全我之前写过的一个 word,这个 word 可能只是注释里的一个单词,YCM 没办法找出它;这个时候我会使用 omnicomple 命令系列。

文档

  1. jedi-vim 插件安装参考文档安装部分: xmfbit.github.io/2018/10/02/…
  2. omnicomplete,vim 万能补全, :help ins-completion
  3. YCM 操作详细参考: github.com/Valloric/Yo…
  4. YCM 配置: zhuanlan.zhihu.com/p/33046090

配置

YCM

YCM 的补全需要对文件进行语法分析,所以需要依赖 .ycm_extra_conf.py 配置文件,生成 .ycm_extra_conf.py 配置文件在 google 上有详细的介绍,我们这里使用 YCM-Generator 插件,可以对 make 编译系统生成需要的配置文件。

"=========================================
" YCM-Generator 插件配置
"=========================================
" ctrl-I 自动生成 .ycm_extra_conf.py 文件
noremap <C-I> :YcmGenerateConfig -c g++ -v -x c++ -f -b make .<CR>
复制代码

上面的配置加到 .vimrc 后,只要在项目根目录打开后执行快捷键 Ctrl - i 后就会自动在当前目录生成配置文件

  1. ctrl + I ,自动生成 .ycm_extra_conf.py 文件
  2. Ctrl + Space ,在任何地方触发完成建议,即使没有字符串前缀也是如此。这对于查看哪些顶级函数可供使用很有用。
  3. :YcmRestartServer ,重新启动
  4. :YcmDiags:YcmDebugInfo ,查询信息
  5. :YcmCompleter 命令,配合其他子选项完成功能,例如, GoToDeclaration 跳转到声明处
搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

omnicomple

Ctrl-X Ctrl-L
Ctrl-X Ctrl-N
Ctrl-X Ctrl-i
Ctrl-X Ctrl-]
Ctrl-X Ctrl-F
Ctrl-X Ctrl-O

有了 YCM 补全为什么需要 omni,YCM 没办法补全 buffer 内的字符串,这个时候就要用 Ctrl-X Ctrl-N

jedi-vim

leader + d
leader + n
leader + r
:Pyimport os
Ctrl + space

说明

  1. centos 系统比较老,使用 YCM 版本不是最新的,我这里为 github.com/Valloric/Yo… 版本为 clang+llvm-3.3-amd64-Ubuntu-10.04.4.tar.gz

语法高亮

插件

vim-polyglot 是一个开箱即用型的语法高亮包,还有对齐功能,支持 134 种语言 ;同时全部语言文件都是针对文件类型进行延迟加载的,不会影响到 vim 的启动速度。

具体的支持语言可以参考 github 上的介绍: github.com/sheerun/vim…

配置

几乎不用加载配置,只需要 vim 打开 syntax 功能。

syntax on
复制代码

缩进线

插件

indentLine 是一个显示竖直对齐线的插件 ,习惯让代码整齐,但是插件只支持空格对齐的代码,所以对于 tab 对齐的不会显示对齐线;因为不同的编辑器对 tab 的展示不太一样,有的展示 4 个空格,有的展示 8 个;我的习惯是让 vim 将输入的 tab 自动转化为 4 个空格,这样的代码在所有的编辑器的展示都是一样的。

tab 自动转化为 4 个空格:

"将输入的TAB自动展开成空格。开启后要输入TAB,需要Ctrl-V<TAB>
set expandtab
"使用每层缩进的空格数
set shiftwidth=4
"编辑时一个TAB字符占多少个空格的位置
set tabstop=4
"方便在开启了et后使用退格(backspace)键,每次退格将删除X个空格
set softtabstop=4
" 使回格键(backspace)正常处理indent(缩进位置), eol(行结束符), start(段首), 很奇怪 Vim 默认竟然不允许在这些地方使用 backspace
set backspace=indent,eol,start
"开启时,在行首按TAB将加入 shiftwidth 个空格,否则加入 tabstop 个空格
set smarttab
复制代码

indentLine 配置:

"打开缩进线
let g:indentLine_enabled = 1
let g:indentLine_char='¦'
复制代码

操作

  1. :IndentLinesToggle ,打开缩进线

语法高亮+缩进线图

搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

语法检查

插件

ale 是一款语法检查的插件,与syntastic类似,但有一个明显的优势,一个是语法检查是异步执行的,因此基本上不会出现卡顿的情况,但它只支持Vim 8.0以上的版本。

Ale 支持多种语言的各种代码分析器,就 C/C++ 而言,就支持:gcc, clang, cppcheck 以及 clang-format 等,需要另行安装并放入 PATH下面,ALE能在你修改了文本后自动调用这些 linter 来分析最新代码,然后将各种 linter 的结果进行汇总并显示再界面上。

因为 LSP 协议支持语法检查,所以 ALE 后面又支持 LSP,又顺便支持了 LSP 语法补全功能,导致 ALE 越来越庞大,后面我基本只将它作为语法检查插件来使用。

ALE 和 clang 的工具集集合起来使用应该很不错, https://github.com/w0rp/ale/blob/master/doc/ale-c.txt 在这里有很多关于 clang 的配置选项,支持 compile_commands.json ,免去头文件查找问题,可惜公司的系统版本较老。

文档

  1. ale 官方文档: github.com/w0rp/ale/tr…
  2. Vim插件之ale: www.cnblogs.com/awakenedy/a…

配置

ale

ale 的配置一般都要指定语言的特定 linter 和 linter 选项;我这里只配置了 C++,C 和 python 的语法检查,C++ 和 C 使用 cppcheck,python 使用 pylint;所以这里需要额外安装 cppcheckpylint 外部程序。

g:ale_linters 用于指定 linter,同时我配置了只在修改 normal 和离开 insert 时才会进行语法检查,避免影响速度。

let g:ale_linters = {
            \ 'cpp': ['cppcheck'],
            \ 'c': ['cppcheck'],
            \ 'python': ['pylint'],
            \}
" normal 模式下文字改变运行 linter
let g:ale_lint_on_text_changed = 'normal'
" 离开 insert 模式的时候运行 linter
let g:ale_lint_on_insert_leave = 1
let g:ale_c_cppcheck_options = '--enable=all'
let g:ale_cpp_cppcheck_options = '--enable=all'
复制代码

以一小段有代码展示 cppcheck 和 ale 的语法检查结果:

int *ptr_list = NULL;
*ptr_list = 1;
复制代码

最下面的状态栏和左边栏都会提示错误: Null pointer dereference ,如下:

搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

关键词搜索

插件

FlyGrep 是从 SpaceVim(spacevim.org/cn/)中移植出来的实时代码检索工具,而且支持正则表达式,配置一个快捷键 Ctrl-F 后就和其他 IDE 的搜索没有什么区别了。

FlyGrep 只能搜索当前目录下的文件,所以如果想搜索整个项目,需要先切换到项目根目录。

文档

  1. FlyGrep 具体介绍和使用方法可以参考官方文档: github.com/wsdjeg/FlyG…

配置

FlyGrep

绑定快捷键 Ctrl-F:

"=========================================
" FlyGrep 插件配置
"=========================================
nnoremap <C-F> :FlyGrep<CR>
复制代码

操作

FlyGrep

Ctrl-F
<Esc>
<Enter>
<Tab>
<S-Tab>
<Home>
<End>

vim 自带

以搜索关键词 "main" 为例:

:vim /main/ % | copen
vim /main/ * | copen
vim /main/ ../** | copen
vim /main path1/** path2/** | copen

说明:

%
copen

搜索图

搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

源文件头文件切换

插件

C++ 项目经常需要在 header 和对应的 source 文件之前切换;CurtineIncSw 就提供了这样的功能,不过它的切换是有一定的前提的:

  1. 头文件和源文件除了后缀名和目录不一样,文件名应该是一样的;比如 foo.c 对应 foo.h
  2. 两个文件要么在同级目录,要么将要打开的文件在已打开文件的子目录

操作:

  1. leader-R :从头文件和源文件互切换

跳转

python 的跳转,我这边使用的是 jedi-vim 插件;C++ 的跳转我使用 vim + ctags 工具;标签的跳转使用 vim-matchup。

ctags 需要自己安装。

过去写几行代码又需要运行一下 ctags 来生成索引,每次生成耗费不少时间。

如今 Vim 8 下面自动异步生成 tags 的工具有很多,这里推荐:vim-gutentags,这个插件主要做两件事情:

  1. 确定文件所属的工程目录,即文件当前路径向上递归查找是否有 .git, .svn, .project 等标志性文件(可以自定义)来确定当前文档所属的工程目录。
  2. 检测同一个工程下面的文件改动,能会自动增量更新对应工程的 .tags 文件。每次改了几行不用全部重新生成,并且这个增量更新能够保证 .tags 文件的符号排序,方便 Vim 中用二分查找快速搜索符号。

配置

vim-gutentags

" gutentags 搜索工程目录的标志,碰到这些文件/目录名就停止向上一级目录递归
let g:gutentags_project_root = ['.root', '.svn', '.git', '.hg', '.project']

" 所生成的数据文件的名称
let g:gutentags_ctags_tagfile = '.tags'

" 将自动生成的 tags 文件全部放入 ~/.cache/tags 目录中,避免污染工程目录
let s:vim_tags = expand('~/.cache/tags')
let g:gutentags_cache_dir = s:vim_tags

" 配置 ctags 的参数
let g:gutentags_ctags_extra_args = ['--fields=+niazS', '--extra=+q']
let g:gutentags_ctags_extra_args += ['--c++-kinds=+px']
let g:gutentags_ctags_extra_args += ['--c-kinds=+px']
复制代码

有了上面的设置,你平时基本感觉不到 tags 文件的生成过程了,只要文件修改过,gutentags 都在后台为你默默打点是否需要更新数据文件,你根本不用管,还会帮你: setlocal tags+=...

为当前文件添加上对应的 tags 文件的路劲而不影响其他文件。得益于 Vim 8 的异步机制,你可以任意随时使用 ctags 相关功能,并且数据库都是最新的。需要注意的是,gutentags 需要靠上面定义的 project_root 里的标志,判断文件所在的工程,如果一个文件没有托管在 .git/.svn 中,gutentags 找不到工程目录的话,就不会为该野文件生成 tags,这也很合理。想要避免的话,你可以在你的野文件目录中放一个名字为 .root 的空白文件,主动告诉 gutentags 这里就是工程目录。

操作

  • 操作:
ctrl+]
ctrl+o
%

文档

  1. stackoverflow.com/questions/1…
  2. vim.wikia.com/wiki/Single…
  3. blog.csdn.net/gangyanlian…
  4. releases.llvm.org/3.7.0/tools…
  5. www.skywind.me/blog/archiv…

文件模版

vim模板插件 segmentfault.com/a/119000000… Vim为特定文件载入模板 blog.csdn.net/demorngel/a…

状态栏

插件

vim-airline 是 powerline 的替代品,并且能够和 tarbar 一起工作。这两个插件装完,状态栏,大纲预览以及任务栏都齐了。

文档

  1. vim-airline 官方文档: github.com/vim-airline…
  2. tarbar 安装文档: www.wklken.me/posts/2015/…
搭建基于 Vim 的 C++和 Python 开发环境[持续更新]

窗口

类/方法/变量相关侧边栏

  • 操作:
  1. F9 打开
  • 插件:
  1. majutsushi/tagbar

上方 Tab 栏

  • 操作:
ctrl+left
ctrl+right
ctrl+n
ctrl+p

C/C++ 格式化

  1. F4,在 normal 模式,格式化文件代码;在 visual 模式,格式化选中的代码

折叠

插件: github.com/tmhedberg/S… 操作:zc关闭折叠并zo打开折叠

缩进

操作: <<>> ,==命令来缩进当前行,可视化模式选择多行,使用=命令缩进选中的行 文档: yyq123.blogspot.com/2010/10/vim…

复制粘贴

vim 复制到 windows

yum install libX11 libX11-devel libXtst-devel libXtst libXt-devel libXt libSM-devel libSM libXpm libXpm-devel
  1. ./configure --prefix=/data/luffichen/bin/vim-8.1 --with-features=huge --with-luajit --enable-luainterp=yes --enable-fail-if-missing --enable-pythoninterp=yes --with-x=yes --enable-gui=auto
  2. 查看是否支持 X11: grep X11 src/auto/config.h 如果有 #define HAVE_X11 1 #define HAVE_X11_XPM_H 1 #define HAVE_X11_SM_SMLIB_H 1 即表示依赖成功
  3. make -j4 && make install
  4. vim --version | grep clipboard 查看是否支持
  5. Run Xshell and connect to the server using the SSH protocol with X11 forwarding,具体的操作:文件-默认会话属性-隧道-X11转移,选择 X Display
  6. 配置ssh, vi /etc/ssh/sshd_config 确认有配置 X11Forwrding yes ,允许SSH的X转发
  7. 安装VcXsrv X11 Server, sourceforge.net/projects/vc… 的剪切板功能貌似对中文支持不好,所以这里使用 VcXsrv)
  8. 打开 XLaunch,选择 multiple windows,和 display number 为 0,start no client,勾选 clipbord
  • 操作:
  1. visual 模式,选择要复制的内容后执行 +y ,即可 安装luajit : blog.csdn.net/tao_627/art…

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

云计算安全与隐私

云计算安全与隐私

Tim Mather、Subra Kumaraswamy、Shahed Latif / 刘戈舟、杨泽明、刘宝旭 / 机械工业出版社华章公司 / 2011-6 / 65.00元

《云计算安全与隐私》可以使你明白当把数据交付给云计算时你所面临的风险,以及为了保障虚拟基础设施和网络应用程序的安全可以采取的行动。本书是由信息安全界知名专家所著,作者在书中给出许多中肯的忠告和建议。本书的读者对象包括:IT职员、信息安全和隐私方面的从业人士、业务经理、服务提供商,以及投资机构等。阅读本书你会了解直到现在还严重匮乏的云计算安全方面的详尽信息。 《云计算安全与隐私》主要内容包括:......一起来看看 《云计算安全与隐私》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具