经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 软件/图像 » Vim » 查看文章
老旧 Linux 系统搭建现代 C++ 开发环境 —— 基于 neovim
来源:cnblogs  作者:goodcitizen  时间:2024/7/31 14:57:44  对本文有异议

问题背景

公司配发的电脑是 macOS,日常开发需要访问 Linux 虚拟机,出于安全方面的考虑,只能通过跳板机登录。这阻止了大多数远程图形界面的使用,让写代码的工作变得复杂起来,市面上非常好用的 VSCode 都用不了。因此考虑基于 vim 搭建一套个人开发环境,需要支持以下特性:

  • 语法高亮 (风格可切换)
  • 自动格式化
  • 函数或变量定义跳转
  • 函数或变量引用跳转
  • 成员函数或变量下拉列表提示
  • 函数或变量 TAB 键自动补齐
  • 快速查找
  • ……

考察了多种方案后,决定基于目前比较流行的 neovim 来打造,不过它面向的是比较新的 Linux 发行版,不知道我这个老的 CentOS7 能不能带起来,本文就是一个探索过程。

系统环境

开始之前,先罗列下老旧系统的配置:

  • 硬件
    • CPU: 2.40GHz * 2 核
    • 内存: 16G
    • 存储: 40G + 100G
  • 软件
    • 系统:CentOS Linux release 7.9.2009 (Core)
    • kernel:3.10.0-1160.21.1.el7.x86_64
    • rpm:4.11.3
    • gcc:4.8.5 (备选 8.2)
    • glibc:2.17
    • make:GNU make 3.82
    • openssl:1.0.2k
    • git:1.8
    • wget:1.14
    • python: 3.6.8

确实是老旧,都是公司成本控制的泪~

软件安装

整个搭建过程是比较坎坷的,常常是装了 Z 之后才发现它依赖 X、Y,去安装 X、Y 的时候又发现一坨问题……这里为了直接上手,改为正叙模式,按这个方式一步步安装、升级,应该是没问题的。如果你的系统上已经存在依赖的软件且版本一致或更新,可以忽略对应安装过程。

在 Linux 上安装软件,一般有源码安装和包管理器安装两种方式,后者在 CentOS 上就是 yum 了,然而软件源提供的软件一般版本较低,有时需要使用前者,这就比较依赖 wget、git、gcc 和 make 了,这也是在上一节中列出他们版本的原因,在开始安装各种软件之前,需要首先升级他们。

基础软件升级

gcc

系统提供的 4.8.5 编译基本是够用的,后面代码格式化需要用到的 clang-format 模块如果是源码方式安装,要求 gcc 至少是 5.1,如果你有 5.1 及以上的 gcc 那更好。没有也没关系,本文会用其它方式绕过,毕竟升级 gcc 是一项大工程,没有半天是搞不定的,太耽误功夫。

虽然不必升级 gcc,但是一些代码库使用的高版本 gcc 默认了 -std=c99 选项,这点对老版本非常不友好,为此需要特意告诉老 gcc 编译器这个选项。具体就是修改 gcc 的 spec 文件,首先是确认当前系统 gcc 加载的 spec 文件:

  1. > strace -e file gcc 2>&1 | grep specs
  2. access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs", R_OK) = -1 ENOENT (No such file or directory)
  3. access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/lib/x86_64-redhat-linux/4.8.5/specs", R_OK) = -1 ENOENT (No such file or directory)
  4. access("/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../x86_64-redhat-linux/lib/specs", R_OK) = -1 ENOENT (No such file or directory)
  5. access("/usr/lib/gcc/x86_64-redhat-linux/specs", R_OK) = -1 ENOENT (No such file or directory)

目前看是没有,需要使用 gcc 析出一份默认的:

  1. > sudo bash -c 'gcc -dumpspecs > /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs'

注意析出的路径就是上面加载路径中的第一条,内容如下:

查看代码
  1.  *asm:
  2. %{m32:--32} %{m32|mx32:;:--64} %{mx32:--x32} %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}
  3. *asm_debug:
  4. %{!g0:%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}} %{fdebug-prefix-map=*:--debug-prefix-map %*}
  5. *asm_final:
  6. %{gsplit-dwarf:
  7. objcopy --extract-dwo %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} %{c:%{o*:%:replace-extension(%{o*:%*} .dwo)}%{!o*:%b.dwo}}%{!c:%b.dwo}
  8. objcopy --strip-dwo %{c:%{o*:%*}%{!o*:%b%O}}%{!c:%U%O} }
  9. *asm_options:
  10. %{-target-help:%:print-asm-header()} %{v} %{w:-W} %{I*} %a %Y %{c:%W{o*}%{!o*:-o %w%b%O}}%{!c:-o %d%w%u%O}
  11. *invoke_as:
  12. %{!fwpa: %{fcompare-debug=*|fdump-final-insns=*:%:compare-debug-dump-opt()} %{!S:-o %|.s |
  13. as %(asm_options) %m.s %A } }
  14. *cpp:
  15. %{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}
  16. *cpp_options:
  17. %(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w} %{f*} %{g*:%{!g0:%{g*} %{!fno-working-directory:-fworking-directory}}} %{O*} %{undef} %{save-temps*:-fpch-preprocess}
  18. *cpp_debug_options:
  19. %{d*}
  20. *cpp_unique_options:
  21. %{!Q:-quiet} %{nostdinc*} %{C} %{CC} %{v} %{I*&F*} %{P} %I %{MD:-MD %{!o:%b.d}%{o*:%.d%*}} %{MMD:-MMD %{!o:%b.d}%{o*:%.d%*}} %{M} %{MM} %{MF*} %{MG} %{MP} %{MQ*} %{MT*} %{!E:%{!M:%{!MM:%{!MT:%{!MQ:%{MD|MMD:%{o*:-MQ %*}}}}}}} %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %{H} %C %{D*&U*&A*} %{i*} %Z %i %{fmudflap:-D_MUDFLAP -include mf-runtime.h} %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h} %{E|M|MM:%W{o*}}
  22. *trad_capable_cpp:
  23. cc1 -E %{traditional|traditional-cpp:-traditional-cpp}
  24. *cc1:
  25. %{!mandroid|tno-android-cc:%(cc1_cpu) %{profile:-p};:%(cc1_cpu) %{profile:-p} %{!mglibc:%{!muclibc:%{!mbionic: -mbionic}}} %{!fno-pic:%{!fno-PIC:%{!fpic:%{!fPIC: -fPIC}}}}}
  26. *cc1_options:
  27. %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} %{g*} %{O*} %{W*&pedantic*} %{w} %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{Qy:} %{-help:--help} %{-target-help:--target-help} %{-version:--version} %{-help=*:--help=%*} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage}
  28. *cc1plus:
  29. *link_gcc_c_sequence:
  30. %{static:--start-group} %G %L %{static:--end-group}%{!static:%G}
  31. *link_ssp:
  32. %{fstack-protector:}
  33. *endfile:
  34. %{!mandroid|tno-android-ld:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} %{mpc32:crtprec32.o%s} %{mpc64:crtprec64.o%s} %{mpc80:crtprec80.o%s} %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s;:%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} %{mpc32:crtprec32.o%s} %{mpc64:crtprec64.o%s} %{mpc80:crtprec80.o%s} %{shared: crtend_so%O%s;: crtend_android%O%s}}
  35. *link:
  36. %{!r:--build-id} --no-add-needed %{!static:--eh-frame-hdr} --hash-style=gnu %{!mandroid|tno-android-ld:%{m32|mx32:;:-m elf_x86_64} %{m32:-m elf_i386} %{mx32:-m elf32_x86_64} %{shared:-shared} %{!shared: %{!static: %{rdynamic:-export-dynamic} %{m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}} %{m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}} %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}} %{static:-static}};:%{m32|mx32:;:-m elf_x86_64} %{m32:-m elf_i386} %{mx32:-m elf32_x86_64} %{shared:-shared} %{!shared: %{!static: %{rdynamic:-export-dynamic} %{m32:-dynamic-linker %{muclibc:/lib/ld-uClibc.so.0;:%{mbionic:/system/bin/linker;:/lib/ld-linux.so.2}}} %{m32|mx32:;:-dynamic-linker %{muclibc:/lib/ld64-uClibc.so.0;:%{mbionic:/system/bin/linker64;:/lib64/ld-linux-x86-64.so.2}}} %{mx32:-dynamic-linker %{muclibc:/lib/ldx32-uClibc.so.0;:%{mbionic:/system/bin/linkerx32;:/libx32/ld-linux-x32.so.2}}}} %{static:-static}} %{shared: -Bsymbolic}}
  37. *lib:
  38. %{!mandroid|tno-android-ld:%{pthread:-lpthread} %{shared:-lc} %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}};:%{pthread:-lpthread} %{shared:-lc} %{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}} %{!static: -ldl}}
  39. *mfwrap:
  40. %{static: %{fmudflap|fmudflapth: --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca} %{fmudflapth: --wrap=pthread_create}} %{fmudflap|fmudflapth: --wrap=main}
  41. *mflib:
  42. %{fmudflap|fmudflapth: -export-dynamic}
  43. *link_gomp:
  44. *libgcc:
  45. %{static|static-libgcc:-lgcc -lgcc_eh}%{!static:%{!static-libgcc:%{!shared-libgcc:-lgcc --as-needed -lgcc_s --no-as-needed}%{shared-libgcc:-lgcc_s%{!shared: -lgcc}}}}
  46. *startfile:
  47. %{!mandroid|tno-android-ld:%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s};:%{shared: crtbegin_so%O%s;: %{static: crtbegin_static%O%s;: crtbegin_dynamic%O%s}}}
  48. *cross_compile:
  49. 0
  50. *version:
  51. 4.8.5
  52. *multilib:
  53. . !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;
  54. *multilib_defaults:
  55. m64
  56. *multilib_extra:
  57. *multilib_matches:
  58. m64 m64;m32 m32;
  59. *multilib_exclusions:
  60. *multilib_options:
  61. m64/m32
  62. *multilib_reuse:
  63. *linker:
  64. collect2
  65. *linker_plugin_file:
  66. *lto_wrapper:
  67. *lto_gcc:
  68. *link_libgcc:
  69. %D
  70. *md_exec_prefix:
  71. *md_startfile_prefix:
  72. *md_startfile_prefix_1:
  73. *startfile_prefix_spec:
  74. *sysroot_spec:
  75. --sysroot=%R
  76. *sysroot_suffix_spec:
  77. *sysroot_hdrs_suffix_spec:
  78. *self_spec:
  79. *cc1_cpu:
  80. %{march=native:%>march=native %:local_cpu_detect(arch) %{!mtune=*:%>mtune=native %:local_cpu_detect(tune)}} %{mtune=native:%>mtune=native %:local_cpu_detect(tune)}
  81. *link_command:
  82. %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S: %(linker) %{!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin: -plugin %(linker_plugin_file) -plugin-opt=%(lto_wrapper) -plugin-opt=-fresolution=%u.res %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} }}%{flto|flto=*:%<fcompare-debug*} %{flto} %{flto=*} %l %{pie:-pie} %{fuse-ld=*:-fuse-ld=%*} %X %{o*} %{e*} %{N} %{n} %{r} %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}} %{static:} %{L*} %(mfwrap) %(link_libgcc) %{!nostdlib:%{!nodefaultlibs:%{fsanitize=address:%{!shared:libasan_preinit%O%s} %{static-libasan:%{!shared:-Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic}}%{!static-libasan:-lasan}} %{fsanitize=thread:%{static-libtsan:%{!shared:-Bstatic --whole-archive -ltsan --no-whole-archive -Bdynamic}}%{!static-libtsan:-ltsan}}}} %o %{fopenmp|ftree-parallelize-loops=*:%:include(libgomp.spec)%(link_gomp)} %{fgnu-tm:%:include(libitm.spec)%(link_itm)} %(mflib) %{fsplit-stack: --wrap=pthread_create} %{fprofile-arcs|fprofile-generate*|coverage:-lgcov} %{!nostdlib:%{!nodefaultlibs:%{fsanitize=address: %{static-libasan:-ldl -lpthread} %{static:%ecannot specify -static with -fsanitize=address} %{fsanitize=thread:%e-fsanitize=address is incompatible with -fsanitize=thread}} %{fsanitize=thread: %{static-libtsan:-ldl -lpthread} %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}}} %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}} %{!nostdlib:%{!nostartfiles:%E}} %{T*} }}}}}}

信息比较多,定位到关键字 *cc1_options:, 在 %{w}%{std*&ansi&trigraphs} 之间添加 -std=c99

  1. > cat /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs.c99 | grep c99
  2. %{pg:%{fomit-frame-pointer:%e-pg and -fomit-frame-pointer are incompatible}} %{!iplugindir*:%{fplugin*:%:find-plugindir()}} %1 %{!Q:-quiet} %{!dumpbase:-dumpbase %B} %{d*} %{m*} %{aux-info*} %{fcompare-debug-second:%:compare-debug-auxbase-opt(%b)} %{!fcompare-debug-second:%{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}}%{!c:%{!S:-auxbase %b}} %{g*} %{O*} %{W*&pedantic*} %{w} -std=c99 %{std*&ansi&trigraphs} %{v:-version} %{pg:-p} %{p} %{f*} %{undef} %{Qn:-fno-ident} %{Qy:} %{-help:--help} %{-target-help:--target-help} %{-version:--version} %{-help=*:--help=%*} %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}} %{fsyntax-only:-o %j} %{-param*} %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants} %{coverage:-fprofile-arcs -ftest-coverage}

再次运行 gcc,确认已加载修改后的 spec 文件:

  1. > gcc -v
  2. Reading specs from /usr/lib/gcc/x86_64-redhat-linux/4.8.5/specs
  3. COLLECT_GCC=gcc
  4. COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
  5. Target: x86_64-redhat-linux
  6. Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
  7. Thread model: posix
  8. gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)

第一行的输出符合预期,整个过程可参考附录 4。

如果不进行这个设置,后面在编译 lsp-server 中的 lsp-kind.nvim & nvim-lspconfig 模块时会失败:

glibc

系统提供的 2.17 不行,clangd 需要至少 2.18,否则 neovim 中跳转相关的键 (gd/gD) 会失效,而 yum 上没有大于 2.17 版本的软件可用,需要手动更新下:

  1. # 通过网盘链接下载 rpm 包
  2. # 链接: https://pan.baidu.com/s/1QAyqa04iZ45q1-HqeYH80Q?pwd=1234 提取码: 1234
  3. > ls -lh *.rpm
  4. -rw-r--r-- 1 yunhai01 DOORGOD 3.6M May 17 16:28 glibc-2.18-11.fc20.x86_64.rpm
  5. -rw-r--r-- 1 yunhai01 DOORGOD 12M May 17 16:28 glibc-common-2.18-11.fc20.x86_64.rpm
  6. -rw-r--r-- 1 yunhai01 DOORGOD 1.1M May 17 16:28 glibc-devel-2.18-11.fc20.x86_64.rpm
  7. -rw-r--r-- 1 yunhai01 DOORGOD 648K May 17 16:28 glibc-headers-2.18-11.fc20.x86_64.rpm
  8. > sudo rpm -Uvh --nodeps --force glibc-*.rpm
  9. > ldd --version
  10. ldd (GNU libc) 2.18
  11. Copyright (C) 2013 Free Software Foundation, Inc.
  12. This is free software; see the source for copying conditions. There is NO
  13. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. Written by Roland McGrath and Ulrich Drepper.

具体升级过程可参考附录 2。

make

系统提供的 3.82 GNU Make 基本够用。

openssl

系统提供的 1.0.2k 基本够用。

git

系统提供的 1.8 版本不行,需要升级到 2.38,否则不能识别 rebase=false 参数,导致插件更新时拉取代码库失败:

当时直接使用 yum install git 升级的版本还是比较低,所以我是手动安装的,但也取了个巧,直接安装了个 rpm 来更新 CentOS7 的软件源:

  1. > sudo yum install https://packages.endpointdev.com/rhel/7/os/x86_64/endpoint-repo.x86_64.rpm
  2. > sudo yum install git
  3. > git --version
  4. git version 2.38.1

从而找到更新版本的 git,省了不少事。后来这个源还更新了,现在安装的话是 2.43 版本。

另外最好更新 /etc/hosts 文件以便加快对 github.com 的访问速度:

  1. > cat /etc/hosts
  2. 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
  3. ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
  4. 140.82.114.3 github.com
  5. 140.82.114.10 nodeload.github.com
  6. 140.82.114.6 api.github.com
  7. 140.82.114.10 codeload.github.com

这里的 ip 都是通过反查相关域名得到的,可能会有所不同,详情参考附录 3。

wget

系统提供的 1.14 版本不行,在拉取部分 lsp-server 时会出错 (cpp/lua),需要升级到 1.21.3:

  1. > curl -o wget-latest.tar.gz http://mirrors.ustc.edu.cn/gnu/wget/wget-latest.tar.gz
  2. > tar xvf wget-latest.tar.gz
  3. > cd wget-1.21.3
  4. > ./configure --with-ssl=openssl
  5. > make -j8
  6. > sudo make install
  7. > wget --version
  8. GNU Wget 1.21.3 built on linux-gnu.
  9. -cares +digest -gpgme +https +ipv6 -iri +large-file -metalink +nls
  10. +ntlm +opie -psl +ssl/openssl
  11. Wgetrc:
  12. /usr/local/etc/wgetrc (system)
  13. Locale:
  14. /usr/local/share/locale
  15. Compile:
  16. gcc -std=gnu11 -DHAVE_CONFIG_H
  17. -DSYSTEM_WGETRC="/usr/local/etc/wgetrc"
  18. -DLOCALEDIR="/usr/local/share/locale" -I. -I../lib -I../lib
  19. -DHAVE_LIBSSL -DNDEBUG -g -O2
  20. Link:
  21. gcc -std=gnu11 -DHAVE_LIBSSL -DNDEBUG -g -O2 -lpcre -lssl -lcrypto
  22. -lz ../lib/libgnu.a
  23. Copyright (C) 2015 Free Software Foundation, Inc.
  24. License GPLv3+: GNU GPL version 3 or later
  25. <http://www.gnu.org/licenses/gpl.html>.
  26. This is free software: you are free to change and redistribute it.
  27. There is NO WARRANTY, to the extent permitted by law.
  28. Originally written by Hrvoje Niksic <hniksic@xemacs.org>.
  29. Please send bug reports and questions to <bug-wget@gnu.org>.

目前的 wget-lastest 指向的最新版本是 1.24.5。

python3

系统提供的 3.6.8 版本勉强够用,clang-format 编译安装要求 python 至少为 3.8 版本,可以选择安装 Python 3.8.1:

  1. > sudo yum install libffi-devel
  2. > wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz
  3. > tar -xvf Python-3.8.1.tgz
  4. > cd Python-3.8.1
  5. > ./configure --prefix=/usr/local/python3
  6. > make -j8
  7. > sudo make altinstall
  8. > sudo ln -sf /usr/local/python3/bin/python3.8 /usr/bin/python3
  9. > sudo ln -sf /usr/local/python3/bin/pip3.8 /usr/bin/pip3

不过可以通过直接下载 clang-format 来忽略这步,所以这里的 python3 没有升级,具体操作步骤在安装 clang-format 时介绍。

cargo

rust 的包管理器,系统未提供,需要单独安装:

  1. > sudo yum install cargo
  2. > cargo --version
  3. cargo 1.65.0

用于后续安装 fd,它是一款 find 的替代者,可以实现更高效的文件查找,目前 yum 上最新的版本是 1.72.1。

go

go 语言编译器,系统未提供,需要单独安装:

  1. > sudo yum install go
  2. > go version
  3. go version go1.17.12 linux/amd64

用来后续编译安装 efm-langserver,它是一款代码审查工具。目前 yum 源最新 go 版本是 1.20.12。为避免后续安装过程中出现网络访问错误的问题,可提前设置以下代理:

  1. > go env -w GO111MODULE=on
  2. > go env -w GOPROXY=https://goproxy.io,direct
  3. > go env -w GOPRIVATE=*.corp.example.com

sqlite3

本地数据库,系统未提供,需要单独安装:

  1. > sudo yum install sqlite sqlite-devel
  2. > sqlite3 --version
  3. 3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

用于后续安装 scheme ,它是一款语法高亮插件,使用 sqlite3 存储信息。

升级后

  • gcc:4.8.5
  • glibc:2.18
  • make:GNU make 3.82
  • openssl:1.0.2k
  • git:2.43
  • wget:1.24.5
  • python: 3.6.8
  • cargo:1.72.1
  • go:1.20.12
  • sqlite3:3.7.17

依赖软件安装

rg

全名 ripgrep,是 grep 替代者,功能更强大,不能直接使用 yum 安装,通过添加 yum 源的方式来曲线安装:

  1. > sudo yum-config-manager --add-repo=https://copr.fedorainfracloud.org/coprs/carlwgeorge/ripgrep/repo/epel-7/carlwgeorge-ripgrep-epel-7.repo
  2. > sudo yum install ripgrep
  3. > rg --version
  4. ripgrep 13.0.0
  5. -SIMD -AVX (compiled)
  6. +SIMD +AVX (runtime)

源是固定的,版本目前仍保持 13.0.0。

fd

全名 fd-find,用来替代 find,功能更强大,有之前安装 cargo 的基础,直接安装:

  1. > cargo install fd-find
  2. > sudo cp ~/.cargo/bin/fd /usr/local/bin/
  3. > fd --version
  4. fd 8.5.3

基于最新的 cargo 1.72.1 安装会报错:

  1. > cargo install fd-find
  2. Updating crates.io index
  3. Downloaded fd-find v10.1.0
  4. ...
  5. warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:8c::649: Network is unreachable)
  6. Downloaded jemalloc-sys v0.5.4+5.3.0-patched
  7. Downloaded 64 crates (8.2 MB) in 3m 10s (largest was `linux-raw-sys` at 1.8 MB)
  8. error: failed to compile `fd-find v10.1.0`, intermediate artifacts can be found at `/tmp/cargo-installBfI2hZ`.
  9. To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
  10. Caused by:
  11. package `clap_complete v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1
  12. Try re-running cargo install with `--locked`

看起来需要升级 rustc (1.74 > 1.72.1),不过看到要安装的 fd-find 版本为 10.1.0,好像受到了启发,直接指定 fd-find 的版本为 8.5.3 重试:

  1. > cargo install fd-find --version 8.5.3
  2. Downloaded fd-find v8.5.3
  3. Downloaded 1 crate (114.1 KB) in 9.31s
  4. Updating crates.io index
  5. Installing fd-find v8.5.3
  6. Updating crates.io index
  7. ...
  8. Downloaded 22 crates (2.2 MB) in 1m 07s (largest was `linux-raw-sys` at 1013.8 KB)
  9. error: failed to compile `fd-find v8.5.3`, intermediate artifacts can be found at `/tmp/cargo-installmg1If6`.
  10. To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
  11. Caused by:
  12. package `clap_complete v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1
  13. Try re-running cargo install with `--locked`

仍然失败,叔可忍婶不可忍,直接按提示加 --locked 选项:

查看代码
  1.  > cargo install fd-find --version 8.5.3 --locked
  2. Updating crates.io index
  3. Installing fd-find v8.5.3
  4. Updating crates.io index
  5. warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2600:9000:20e4:fe00:1f:a9f5:69c0:93a1: Network is unreachable)
  6. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
  7. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  8. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  9. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  10. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  11. warning: package `crossbeam-channel v0.5.6` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked
  12. Updating crates.io index
  13. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
  14. Downloaded ctrlc v3.2.3
  15. Downloaded termcolor v1.1.3
  16. Downloaded crossbeam-utils v0.8.12
  17. Downloaded time v0.1.44
  18. Downloaded clap_complete v4.0.5
  19. Downloaded clap_derive v4.0.21
  20. Downloaded num-traits v0.2.15
  21. Downloaded thread_local v1.1.4
  22. Downloaded proc-macro2 v1.0.47
  23. Downloaded memchr v2.5.0
  24. Downloaded jemallocator v0.5.0
  25. Downloaded iana-time-zone v0.1.51
  26. Downloaded os_str_bytes v6.3.0
  27. Downloaded unicode-ident v1.0.5
  28. Downloaded globset v0.4.9
  29. Downloaded heck v0.4.0
  30. Downloaded clap v4.0.22
  31. Downloaded num-integer v0.1.45
  32. Downloaded proc-macro-error v1.0.4
  33. Downloaded quote v1.0.21
  34. Downloaded fs_extra v1.2.0
  35. Downloaded anyhow v1.0.66
  36. Downloaded fnv v1.0.7
  37. Downloaded nix v0.24.2
  38. Downloaded terminal_size v0.2.1
  39. Downloaded clap_lex v0.3.0
  40. Downloaded ignore v0.4.18
  41. Downloaded proc-macro-error-attr v1.0.4
  42. Downloaded io-lifetimes v0.7.4
  43. Downloaded log v0.4.17
  44. Downloaded regex v1.6.0
  45. Downloaded cc v1.0.73
  46. Downloaded once_cell v1.15.0
  47. Downloaded num_cpus v1.13.1
  48. Downloaded syn v1.0.103
  49. Downloaded rustix v0.35.12
  50. Downloaded nix v0.25.0
  51. Downloaded autocfg v1.1.0
  52. Downloaded crossbeam-channel v0.5.6
  53. Downloaded regex-syntax v0.6.27
  54. Downloaded bstr v0.2.17
  55. Downloaded chrono v0.4.22
  56. Downloaded linux-raw-sys v0.0.46
  57. warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:8c::649: Network is unreachable)
  58. Downloaded walkdir v2.3.2
  59. Downloaded jemalloc-sys v0.5.2+5.3.0-patched
  60. Downloaded aho-corasick v0.7.19
  61. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `libc v0.2.136` failed to transfer more than 10 bytes in 30s)
  62. Downloaded libc v0.2.136
  63. Downloaded 47 crates (5.7 MB) in 3m 17s
  64. Compiling libc v0.2.136
  65. Compiling cfg-if v1.0.0
  66. Compiling version_check v0.9.4
  67. Compiling proc-macro2 v1.0.47
  68. Compiling unicode-ident v1.0.5
  69. Compiling bitflags v1.3.2
  70. Compiling quote v1.0.21
  71. Compiling autocfg v1.1.0
  72. Compiling memchr v2.5.0
  73. Compiling proc-macro-error-attr v1.0.4
  74. Compiling io-lifetimes v0.7.4
  75. Compiling syn v1.0.103
  76. Compiling proc-macro-error v1.0.4
  77. Compiling log v0.4.17
  78. Compiling rustix v0.35.12
  79. Compiling num-traits v0.2.15
  80. Compiling crossbeam-utils v0.8.12
  81. Compiling cc v1.0.73
  82. Compiling fs_extra v1.2.0
  83. Compiling once_cell v1.15.0
  84. Compiling linux-raw-sys v0.0.46
  85. Compiling jemalloc-sys v0.5.2+5.3.0-patched
  86. Compiling aho-corasick v0.7.19
  87. Compiling num-integer v0.1.45
  88. Compiling os_str_bytes v6.3.0
  89. Compiling regex-syntax v0.6.27
  90. Compiling heck v0.4.0
  91. Compiling clap_derive v4.0.21
  92. Compiling regex v1.6.0
  93. Compiling clap_lex v0.3.0
  94. Compiling terminal_size v0.2.1
  95. Compiling bstr v0.2.17
  96. Compiling atty v0.2.14
  97. Compiling lazy_static v1.4.0
  98. Compiling strsim v0.10.0
  99. Compiling same-file v1.0.6
  100. Compiling fnv v1.0.7
  101. Compiling termcolor v1.1.3
  102. Compiling anyhow v1.0.66
  103. Compiling clap v4.0.22
  104. Compiling globset v0.4.9
  105. Compiling walkdir v2.3.2
  106. Compiling thread_local v1.1.4
  107. Compiling nix v0.25.0
  108. Compiling nix v0.24.2
  109. Compiling dirs-sys-next v0.1.2
  110. Compiling time v0.1.44
  111. Compiling fd-find v8.5.3
  112. Compiling ansi_term v0.12.1
  113. Compiling iana-time-zone v0.1.51
  114. Compiling chrono v0.4.22
  115. Compiling lscolors v0.12.0
  116. Compiling dirs-next v2.0.0
  117. Compiling argmax v0.3.1
  118. Compiling ctrlc v3.2.3
  119. Compiling ignore v0.4.18
  120. Compiling clap_complete v4.0.5
  121. Compiling jemallocator v0.5.0
  122. Compiling crossbeam-channel v0.5.6
  123. Compiling users v0.11.0
  124. Compiling num_cpus v1.13.1
  125. Compiling humantime v2.1.0
  126. Compiling normpath v0.3.2
  127. Finished release [optimized] target(s) in 10m 44s
  128. warning: the following packages contain code that will be rejected by a future version of Rust: fs_extra v1.2.0
  129. note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
  130. Installing /home/users/yunhai01/.cargo/bin/fd
  131. Installed package `fd-find v8.5.3` (executable `fd`)
  132. warning: be sure to add `/home/users/yunhai01/.cargo/bin` to your PATH to be able to run the installed binaries

这回成功了。尝试为之前安装失败的 10.1.0 版本增加 --locked 选项:

  1. > cargo install fd-find --locked
  2. Updating crates.io index
  3. Installing fd-find v10.1.0
  4. Updating crates.io index
  5. warning: package `libc v0.2.154` in Cargo.lock is yanked in registry `crates-io`, consider running without --locked
  6. Updating crates.io index
  7. Downloaded proc-macro2 v1.0.81
  8. Downloaded anyhow v1.0.82
  9. Downloaded serde v1.0.200
  10. Downloaded errno v0.3.8
  11. Downloaded cc v1.0.96
  12. Downloaded syn v2.0.60
  13. Downloaded libc v0.2.154
  14. Downloaded linux-raw-sys v0.4.13
  15. Downloaded 8 crates (2.8 MB) in 1m 27s (largest was `linux-raw-sys` at 1.5 MB)
  16. error: failed to compile `fd-find v10.1.0`, intermediate artifacts can be found at `/tmp/cargo-installVoh51U`.
  17. To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
  18. Caused by:
  19. package `clap_builder v4.5.2` cannot be built because it requires rustc 1.74 or newer, while the currently active rustc version is 1.72.1

仍然不行,看来回退 8.5.3 是唯一的解决办法。之前还探索过将 cargo 版本降为 1.65.0:

  1. > sudo yum remove cargo
  2. > sudo yum install cargo-1.65.0-1.el7.x86_64
  3. Loaded plugins: fastestmirror, langpacks, versionlock
  4. Loading mirror speeds from cached hostfile
  5. Excluding 1 update due to versionlock (use "yum versionlock status" to show it)
  6. No package cargo-1.65.0-1.el7.x86_64 available.
  7. Error: Nothing to do

未能成功。在网上也没搜到 1.65.0 的 cargo rpm 包,只能作罢。不清楚为何 1.72.1 的 cargo 要求 1.74 的 rustc,严重怀疑这是一个 bug。

书归正题,在安装完 fd 8.5.3 后需要按提示将 fd 移到 /usr/loca/bin:

  1. > sudo cp /home/users/yunhai01/.cargo/bin/fd /usr/local/bin/
  2. > fd --version
  3. fd 8.5.3

否则 neovim 找不到。

tree-sitter

是一个解析器生成工具和增量解析库,在 nvim 中主要用作 latex 语言解析器、以及 rainbow-delimiters.nvim 和 nvim-treesitter.nvim 插件的底层支持。rainbow-delimiters 主要用于多种语言的语法高亮,特别是多括号的展示;nvim-treesitter 主要用于高效代码导航与编辑,是 IDE 不可或缺的底层组件。

可以使用 cargo 安装:

  1. > cargo install tree-sitter-cli

会遇到和安装 fd 类似的问题:

查看代码
  1.  > cargo install tree-sitter-cli
  2. Updating crates.io index
  3. Installing tree-sitter-cli v0.22.6
  4. Updating crates.io index
  5. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30001 milliseconds with 0 out of 0 bytes received)
  6. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30000 milliseconds with 0 out of 0 bytes received)
  7. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  8. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  9. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation timed out after 30001 milliseconds with 0 out of 0 bytes received)
  10. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  11. warning: spurious network error (3 tries remaining): [28] Timeout was reached (Operation too slow. Less than 10 bytes/sec transferred the last 30 seconds)
  12. Downloaded httpdate v1.0.3
  13. Downloaded equivalent v1.0.1
  14. Downloaded tiny_http v0.12.0
  15. Downloaded anstyle-query v1.1.0
  16. Downloaded ascii v1.1.0
  17. Downloaded dirs-sys v0.4.1
  18. Downloaded serde_derive v1.0.203
  19. Downloaded tempfile v3.10.1
  20. Downloaded clap_builder v4.5.6
  21. Downloaded webbrowser v1.0.1
  22. Downloaded tree-sitter-config v0.22.6
  23. Downloaded tree-sitter-tags v0.22.6
  24. Downloaded proc-macro2 v1.0.85
  25. Downloaded percent-encoding v2.3.1
  26. Downloaded unicode-normalization v0.1.23
  27. Downloaded semver v1.0.23
  28. Downloaded libloading v0.8.3
  29. Downloaded filetime v0.2.23
  30. Downloaded idna v0.5.0
  31. Downloaded ahash v0.8.11
  32. Downloaded itoa v1.0.11
  33. Downloaded form_urlencoded v1.2.1
  34. Downloaded zerocopy v0.7.34
  35. Downloaded wasmparser v0.206.0
  36. Downloaded option-ext v0.2.0
  37. Downloaded dirs v5.0.1
  38. Downloaded serde_json v1.0.117
  39. Downloaded chunked_transfer v1.5.0
  40. Downloaded ryu v1.0.18
  41. Downloaded tree-sitter v0.22.6
  42. warning: spurious network error (3 tries remaining): [35] SSL connect error (TCP connection reset by peer)
  43. Downloaded thiserror-impl v1.0.61
  44. Downloaded clap_lex v0.7.1
  45. Downloaded serde v1.0.203
  46. Downloaded unicode-bidi v0.3.15
  47. Downloaded glob v0.3.1
  48. Downloaded tree-sitter-loader v0.22.6
  49. Downloaded indexmap v2.2.6
  50. Downloaded fastrand v2.1.0
  51. Downloaded url v2.5.0
  52. Downloaded indoc v2.0.5
  53. Downloaded tinyvec_macros v0.1.1
  54. Downloaded rustc-hash v1.1.0
  55. Downloaded clap v4.5.6
  56. Downloaded html-escape v0.2.13
  57. Downloaded clap_derive v4.5.5
  58. Downloaded tree-sitter-highlight v0.22.6
  59. Downloaded fs4 v0.8.3
  60. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `difference v2.0.0` failed to transfer more than 10 bytes in 30s)
  61. Downloaded difference v2.0.0
  62. warning: spurious network error (3 tries remaining): [7] Couldn't connect to server (Failed to connect to 2a04:4e42:1a::649: Network is unreachable)
  63. Downloaded utf8-width v0.1.7
  64. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `hashbrown v0.14.5` failed to transfer more than 10 bytes in 30s)
  65. Downloaded hashbrown v0.14.5
  66. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `smallbitvec v2.5.3` failed to transfer more than 10 bytes in 30s)
  67. Downloaded smallbitvec v2.5.3
  68. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `thiserror v1.0.61` failed to transfer more than 10 bytes in 30s)
  69. Downloaded thiserror v1.0.61
  70. warning: spurious network error (3 tries remaining): [28] Timeout was reached (download of `tinyvec v1.6.0` failed to transfer more than 10 bytes in 30s)
  71. Downloaded tinyvec v1.6.0
  72. Downloaded 53 crates (2.7 MB) in 4m 35s
  73. error: failed to compile `tree-sitter-cli v0.22.6`, intermediate artifacts can be found at `/tmp/cargo-installFBNfkt`.
  74. To reuse those artifacts with a future compilation, set the environment variable `CARGO_TARGET_DIR` to that path.
  75. Caused by:
  76. package `tree-sitter-highlight v0.22.6` cannot be built because it requires rustc 1.74.1 or newer, while the currently active rustc version is 1.72.1
  77. Try re-running cargo install with `--locked`

增加 --locked 选项应该可以解决问题,使用 cargo 1.72.1 目前安装的版本为 0.22.6,这个版本运行依赖较高的 glibc,所以放弃。

通过官方提示的 npm 方式安装的结果也差不多:

  1. > npm install tree-sitter-cli
  2. added 1 package in 10m
  3. > ls -lh node_modules/tree-sitter-cli/
  4. total 25M
  5. -rwxr-xr-x 1 yunhai01 DOORGOD 303 Jun 7 12:13 cli.js
  6. -rw-r--r-- 1 yunhai01 DOORGOD 14K Jun 7 12:13 dsl.d.ts
  7. -rwxr-xr-x 1 yunhai01 DOORGOD 3.4K Jun 7 12:13 install.js
  8. -rw-r--r-- 1 yunhai01 DOORGOD 1.1K Jun 7 12:13 LICENSE
  9. -rw-r--r-- 1 yunhai01 DOORGOD 534 Jun 7 12:13 package.json
  10. -rw-r--r-- 1 yunhai01 DOORGOD 1.7K Jun 7 12:13 README.md
  11. -rwxr-xr-x 1 yunhai01 DOORGOD 25M Jun 7 12:23 tree-sitter
  12. > node_modules/tree-sitter-cli/tree-sitter --version
  13. node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.25' not found (required by node_modules/tree-sitter-cli/tree-sitter)
  14. node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.29' not found (required by node_modules/tree-sitter-cli/tree-sitter)
  15. node_modules/tree-sitter-cli/tree-sitter: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node_modules/tree-sitter-cli/tree-sitter)

最早之前安装的 0.20.7 版本是 ok 的,想通过这种方式安装的朋友,可以指定版本试一下。注意这两种方式安装后的文件分别位于 ~/.cargo/bin./node_modules/tree-sitter-cli 下,需要手动复制到 /usr/local/bin 以便生效。

现在介绍第三种安装方式,不依赖 cargo、npm 等包管理器,直接定位到 tree-sitter 官方下载页面,选择 0.20.4 版本,对于我的 CentOS7 x64 版本,选择 tree-sitter-linux-x64.gz 下载即可:

  1. > gunzip tree-sitter-linux-x64.gz
  2. > chmod u+x tree-sitter-linux-x64
  3. > sudo mv tree-sitter-linux-x64 /usr/local/bin
  4. > tree-sitter --version
  5. tree-sitter 0.20.4 (714bfd47a744ab44b904375c177a24c0614ef49c)

按上一面一步步执行就安装好了,亲测高于 0.20.4 的版本就有 glibc 兼容问题 (>2.18)。

efm-langserver

实现智能 IDE 的核心,基于 go 语言开发,使用 go 编译安装:

  1. > go install github.com/mattn/efm-langserver@latest

安装后没有找到 efm-langserver,经查,go 1.20 之后,需要通过 GOPATH 环境变量来指定安装目录:

  1. > export GOPATH=/ext/tools
  2. > go install github.com/mattn/efm-langserver@latest
  3. go: downloading github.com/mattn/efm-langserver v0.0.53
  4. go: downloading github.com/sourcegraph/jsonrpc2 v0.2.0
  5. go: downloading gopkg.in/yaml.v3 v3.0.1
  6. go: downloading github.com/mattn/go-unicodeclass v0.0.2
  7. go: downloading github.com/reviewdog/errorformat v0.0.0-20240311054359-739e471a49b3

同样需要复制到 /usr/local/bin 目录以便全局生效:

  1. > sudo cp bin/efm-langserver /usr/local/bin
  2. > efm-langserver -v
  3. efm-langserver 0.0.53 (rev: HEAD/go1.20.12)

比之前安装的版本略高一些:

  1. > efm-langserver -v
  2. efm-langserver 0.0.44 (rev: 36a4d81/go1.17.12)

Font

下载可支持符号的字体,例如:Nerd Font,在 macOS 上的安装非常简单,直接双击 ttf 文件安装:

然后在 macOS 终端上指定该字体,这里我使用的是 iTerm2,其它终端大同小异:

iTerm2 有以下 UI 路径:iTerm2 -> settings -> Profiles -> Default -> Text -> Font。下面是安装带符号字体前后的对比:

状态栏很多不能显示的符号都正常了 (标签页的仍保持问号,可能是一个特殊符号 Nerd Font 不支持)。

neovim

IDE 的载体,不使用 yum 安装,原因是 yum 上目前只有 0.3 版本的 neovim,而支持现代化 IDE 核心的 packer 包管理器至少需要 0.7 版本。这里使用 curl 直接下载最新版本:

  1. > curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage

启动:

  1. > chmod u+x nvim.appimage
  2. > ./nvim.appimage

报错:

  1. /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim)
  2. /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /tmp/.mount_nvim.aw3KspQ/usr/bin/nvim)

看起来需要升级 glibc 2.29,为了避免再次更新 glibc,这里直接选择可以成功安装的 neovim 0.9.2 版本:

  1. > wget https://github.com/neovim/neovim/releases/download/v0.9.2/nvim.appimage

友情提示:可以在 web 端下载后传递给虚拟机,macOS 访问 github 要比虚拟机快许多。

下载成功后,运行 nvim.appimage 可以自动释放目标文件:

  1. > chmod u+x nvim.appimage
  2. > ./nvim.appimage

如果运行后没有产生 squashfs-root 目录,说明系统缺乏 FUSE (用户空间文件系统),需要手动释放一下:

  1. > ./nvim.appimage --appimage-extract

设置到 /usr/local/bin 后就可以被全局引用了:

  1. > sudo ln -s $PWD/squashfs-root/AppRun /usr/local/bin/nvim
  2. > nvim --version
  3. NVIM v0.9.2
  4. Build type: Release
  5. LuaJIT 2.1.1692716794
  6. system vimrc file: "$VIM/sysinit.vim"
  7. fall-back for $VIM: "/__w/neovim/neovim/build/nvim.AppDir/usr/share/nvim"
  8. Run :checkhealth for more info

nvimdots

IDE 的实现,按照 github 主页 README 的说明直接安装:

  1. if command -v curl >/dev/null 2>&1; then
  2. bash -c "$(curl -fsSL https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
  3. else
  4. bash -c "$(wget -O- https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
  5. fi

脚本会自动判断 neovim 版本并进行适配:

  1. > bash -c "$(wget -O- https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh)"
  2. --2024-05-24 15:32:21-- https://raw.githubusercontent.com/ayamir/nvimdots/HEAD/scripts/install.sh
  3. Resolving raw.githubusercontent.com... 185.199.108.133, 185.199.109.133, 185.199.111.133, ...
  4. Connecting to raw.githubusercontent.com|185.199.108.133|:443... connected.
  5. HTTP request sent, awaiting response... 200 OK
  6. Length: 7830 (7.6K) [text/plain]
  7. Saving to: STDOUT
  8. - 100%[======================================================================================================>] 7.65K 6.79KB/s in 1.1s
  9. 2024-05-24 15:32:25 (6.79 KB/s) - written to stdout [7830/7830]
  10. ==> This script will install ayamir/nvimdots to:
  11. /home/users/yunhai01/.config/nvim
  12. Press RETURN/ENTER to continue or any other key to abort...
  13. ==> Validating SSH connection...
  14. Do you prefer to use SSH to fetch and update plugins? (otherwise HTTPS) [Y/n]:
  15. ==> Checking 'git clone' preferences...
  16. Would you like to perform a shallow clone ('--depth=1')? [Y/n]:
  17. ==> Fetching in progress...
  18. Cloning into '/home/users/yunhai01/.config/nvim'...
  19. remote: Enumerating objects: 170, done.
  20. remote: Counting objects: 100% (170/170), done.
  21. remote: Compressing objects: 100% (162/162), done.
  22. remote: Total 170 (delta 5), reused 73 (delta 0), pack-reused 0
  23. Receiving objects: 100% (170/170), 108.87 KiB | 203.00 KiB/s, done.
  24. Resolving deltas: 100% (5/5), done.
  25. ==> Spawning Neovim and fetching plugins... (You'll be redirected shortly)
  26. ==> NOTE: Please make sure you have a Rust Toolchain installed via `rustup`! Otherwise, unexpected things may
  27. happen. See: https://www.rust-lang.org/tools/install.
  28. ==> If lazy.nvim failed to fetch any plugin(s), maunally execute `:Lazy sync` until everything is up-to-date.
  29. Thank you for using this set of configuration!
  30. - Project Homepage:
  31. https://github.com/ayamir/nvimdots
  32. - Further documentation (including executables you must install for full functionality):
  33. https://github.com/ayamir/nvimdots/wiki/Prerequisites
  34. Press RETURN/ENTER to continue or any other key to abort...

执行过程中会让用户进行若干选项,都按默认处理就可以了。到这里所有必需软件就都安装完成了,按任意键将进入插件的安装,具体内容在下一节介绍。

安装后的目录位于:~/.config/nvim/。注意这里不要选择 neovim 0.8.1 (说的就是我),否则后面启动插件管理器时会报错:

  1. Error executing Lua callback: ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: Vim(append):Error executing lua callback: ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiter
  2. s.lua:50: attempt to call field 'get_lang' (a nil value)
  3. stack traceback:
  4. ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:50: in function 'attach'
  5. ...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:151: in function <...zy/rainbow-delimiters.nvim/plugin/rainbow-delimiters.lua:151>
  6. [C]: in function '__newindex'
  7. ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: in function 'mount'
  8. ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:75: in function 'init'
  9. ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:53: in function 'create'
  10. ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:38: in function 'show'
  11. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:38: in function 'command'
  12. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:24: in function 'cmd'
  13. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:111: in function <...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:98>
  14. stack traceback:
  15. [C]: in function '__newindex'
  16. ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:159: in function 'mount'
  17. ...l/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/float.lua:75: in function 'init'
  18. ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:53: in function 'create'
  19. ...al/share/nvim/site/lazy/lazy.nvim/lua/lazy/view/init.lua:38: in function 'show'
  20. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:38: in function 'command'
  21. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:24: in function 'cmd'
  22. ...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:111: in function <...hare/nvim/site/lazy/lazy.nvim/lua/lazy/view/commands.lua:98>

基本无解。

开发环境搭建

框架好比是毛坯房,想要入住还得“精装修”一下,主要是安装各种插件,以及本地化配置。

插件安装

同许多 IDE 一样,vim 很多功能是通过插件实现的,插件本身需要管理,这就催生了形形色色的插件管理器,知名的有 vim-plug、Vundle;vim 进化到 neovim 之后,有两个主要的插件管理器,一个是 packer,另一个是 lazy,两个都很好用,之前 nvimdots 使用的 packer,后来更新到了 lazy,可以有效的提升 neovim 的启动速度。

lazy

书接上节,在 nvimdots 安装结束后,按任意键将启动 nvim、自动拉起插件更新:

这个界面静静等待即可,最终都能安装成功:

在 lazy 插件管理页面,输入标签后面的字符可实现跳转,例如 U 跳转到更新插件页面。

也可以直接在命令行输入 :Lazy sync 来切换到 Sync 标签:

其它也类似,不再赘述。当所有插件安装结束后,q 退出界面。与原先的 packer 界面相比:

简直像从远古社会跨进到了现代社会。退出 lazy、退出 nvim,插件安装路径位于:~/.local/share/nvim 目录下。再次进入 nvim,将看到欢迎界面:

基本功能已经可用,有几个未安装的插件将继续安装。

mason

mason 也是一个插件管理器,聚焦于 lsp 服务、dap 服务、linter 和 formatter 方向,通过它可以让 nvim 轻松支持多种编程语言的智能化展示。通过 :Mason 启动:

可以观察到系统可用的语言插件、安装成功的、安装失败的,这里主要需要处理 2 个插件的安装。

clangd

从上面的日志可以看出,安装失败的原因主要是从网络获取 clangd 包失败,这里改为手动下载:

  1. > wget https://github.com/clangd/clangd/releases/download/18.1.3/clangd-linux-18.1.3.zip
  2. > mv clangd-linux-18.1.3.zip ~/.local/share/nvim/mason/packages
  3. > cd ~/.local/share/nvim/mason/packages
  4. > unzip clangd-linux-18.1.3.zip
  5. > cd ../bin
  6. > ln -s $PWD/../packages/clangd_18.1.3/bin/clangd clangd
  7. > ./clangd --version
  8. clangd version 18.1.3 (https://github.com/llvm/llvm-project c13b7485b87909fcf739f62cfa382b55407433c0)
  9. Features: linux+grpc
  10. Platform: x86_64-unknown-linux-gnu

解压并替换到目标目录、设置命令软链接后,重启 nvim 查看:

安装成功,如果 nvim 仍显示安装 clangd,就多重启几次,甚至重启下机器。

clang-format

查看 clang-format 错误日志:

没看出来安装失败的直接原因,这里改为手动下载:

  1. > wget -c https://github.com/muttleyxd/clang-tools-static-binaries/releases/download/master-1d7ec53d/clang-format-10_linux-amd64
  2. > chmod u+x clang-format-10_linux-arm64
  3. > mkdir -p ~/.local/share/nvim/mason/packages/clang-format/bin
  4. > mv clang-format-10_linux-amd64 ~/.local/share/nvim/mason/packages/clang-format/bin
  5. > cd ~/.local/share/nvim/mason/bin
  6. > ln -s $PWD/../packages/clang-format/bin/clang-format-10_linux-amd64 clang-format
  7. > ./clang-format --version
  8. clang-format version 10.0.1

替换到目标目录、设置命令软链接后,重启 nvim 查看:

安装成功。如果想让 Mason 安装 clang-format,除了之前介绍的升级 python3 步骤外,还需要以下操作:

  1. > sudo pip3 install wheel
  2. # 进入 nvim
  3. MasonInstall clang-format

最后还有两个插件 python-lsp-server & gopls 没安装成功,分别是 python 与 go 语言 lspserver,由于本文着重介绍 C/C++ 环境的搭建,这个偏离主题就不再赘述了,有需求的小伙伴可以在 nvimdots 中提问寻求帮助。

如果不想看到每次在启动时它们的报错信息,可以选择不加载它们,具体操作步骤详见配置一节。

配置

各种功能插件安装完成后,还需要修改化配置一番,为了方便调用 neovim,在 bash 启动脚本中增加以下内容:

  1. alias vi=nvim
  2. alias vim=nvim

这样就可以使用 vi 或 vim 代替 nvim 了,相当于替换了默认的 vim 编辑器,如果想调用原始的 vim 编辑器,需要输入完整路径:

  1. > /usr/bin/vi

在进行配置之前,首先对 nvim 进行一次自我体验,这主要是通过 :checkhealth 命令来完成,下面是完整的 checkhealth 输出:

查看代码
  1.  
  2. ==============================================================================
  3. hop: require("hop.health").check()
  4. Ensuring keys are unique ~
  5. - OK Keys are unique
  6. Checking for deprecated features ~
  7. - OK All good
  8. ==============================================================================
  9. lazy: require("lazy.health").check()
  10. lazy.nvim ~
  11. - OK Git installed
  12. - OK no existing packages found by other package managers
  13. - OK packer_compiled.lua not found
  14. ==============================================================================
  15. lspsaga: require("lspsaga.health").check()
  16. Lspsaga.nvim report ~
  17. - OK `tree-sitter` found
  18. - OK tree-sitter `markdown` parser found
  19. - OK tree-sitter `markdown_inline` parser found
  20. ==============================================================================
  21. luasnip: require("luasnip.health").check()
  22. luasnip ~
  23. - WARNING For Variable/Placeholder-transformations, luasnip requires
  24. the jsregexp library. See `:help |luasnip-lsp-snippets-transformations`| for advice
  25. ==============================================================================
  26. mason: require("mason.health").check()
  27. mason.nvim ~
  28. - OK mason.nvim version v1.10.0
  29. - OK PATH: prepend
  30. - OK Providers:
  31. mason.providers.registry-api
  32. mason.providers.client
  33. - OK neovim version >= 0.7.0
  34. mason.nvim [Registries] ~
  35. - OK Registry `github.com/mason-org/mason-registry version: 2024-06-07-fast-test` is installed.
  36. mason.nvim [Core utils] ~
  37. - OK unzip: `UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spieler. Send`
  38. - OK wget: `GNU Wget 1.24.5 built on linux-gnu.`
  39. - OK curl: `curl 7.87.0 (x86_64-pc-linux-muslx32) libcurl/7.87.0 OpenSSL/1.1.1s zlib/1.2.12 libssh2/1.9.0 nghttp2/1.43.0`
  40. - OK gzip: `gzip 1.5`
  41. - OK gtar: `tar (GNU tar) 1.26`
  42. - OK bash: `GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)`
  43. - OK sh: `Ok`
  44. mason.nvim [Languages] ~
  45. - WARNING luarocks: not available
  46. - ADVICE:
  47. - spawn: luarocks failed with exit code - and signal -. luarocks is not executable
  48. - WARNING Ruby: not available
  49. - ADVICE:
  50. - spawn: ruby failed with exit code - and signal -. ruby is not executable
  51. - WARNING RubyGem: not available
  52. - ADVICE:
  53. - spawn: gem failed with exit code - and signal -. gem is not executable
  54. - WARNING Composer: not available
  55. - ADVICE:
  56. - spawn: composer failed with exit code - and signal -. composer is not executable
  57. - WARNING PHP: not available
  58. - ADVICE:
  59. - spawn: php failed with exit code - and signal -. php is not executable
  60. - OK node: `v16.18.1`
  61. - OK cargo: `cargo 1.72.1`
  62. - WARNING julia: not available
  63. - ADVICE:
  64. - spawn: julia failed with exit code - and signal -. julia is not executable
  65. - OK Go: `go version go1.20.12 linux/amd64`
  66. - OK python: `Python 3.6.8`
  67. - OK java: `openjdk version "1.8.0_322"`
  68. - OK pip: `pip 9.0.3 from /usr/lib/python3.6/site-packages (python 3.6)`
  69. - OK python venv: `Ok`
  70. - OK javac: `Ok`
  71. - OK npm: `8.19.2`
  72. mason.nvim [GitHub] ~
  73. - OK GitHub API rate limit. Used: 1. Remaining: 59. Limit: 60. Reset: Fri 07 Jun 2024 04:40:44 PM CST.
  74. Install and authenticate via gh-cli to increase rate limit.
  75. ==============================================================================
  76. neoconf: require("neoconf.health").check()
  77. neoconf.nvim ~
  78. - OK **treesitter-nvim** is installed
  79. - OK **TreeSitter jsonc** parser is installed
  80. - WARNING **neodev.nvim** is not installed. You won't get any proper completion for your Neovim config.
  81. - OK **lspconfig** is installed
  82. - OK **lspconfig jsonls** is installed
  83. - OK **lspconfig lua_ls** is installed
  84. ==============================================================================
  85. null-ls: require("null-ls.health").check()
  86. - OK clang_format: the command "clang-format" is executable.
  87. - OK prettier: the command "prettier" is executable.
  88. - OK gofumpt: the command "gofumpt" is executable.
  89. - OK shfmt: the command "shfmt" is executable.
  90. - OK stylua: the command "stylua" is executable.
  91. - OK vint: the command "vint" is executable.
  92. - OK goimports: the command "goimports" is executable.
  93. ==============================================================================
  94. nvim: require("nvim.health").check()
  95. Configuration ~
  96. - OK no issues found
  97. Runtime ~
  98. - OK $VIMRUNTIME: /ext/tools/squashfs-root/usr/share/nvim/runtime
  99. Performance ~
  100. - OK Build type: Release
  101. Remote Plugins ~
  102. - WARNING "wilder.nvim" is not registered.
  103. - WARNING Out of date
  104. - ADVICE:
  105. - Run `:UpdateRemotePlugins`
  106. terminal ~
  107. - key_backspace (kbs) terminfo entry: `key_backspace=\177`
  108. - key_dc (kdch1) terminfo entry: `key_dc=\E[3~`
  109. - $SSH_TTY="/dev/pts/0"
  110. ==============================================================================
  111. nvim-treesitter: require("nvim-treesitter.health").check()
  112. Installation ~
  113. - OK `tree-sitter` found 0.20.4 (714bfd47a744ab44b904375c177a24c0614ef49c) (parser generator, only needed for :TSInstallFromGrammar)
  114. - OK `node` found v16.18.1 (only needed for :TSInstallFromGrammar)
  115. - OK `git` executable found.
  116. - OK `cc` executable found. Selected from { vim.NIL, "cc", "gcc", "clang", "cl", "zig" }
  117. Version: cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44)
  118. - OK Neovim was compiled with tree-sitter runtime ABI version 14 (required >=13). Parsers must be compatible with runtime ABI.
  119. OS Info:
  120. {
  121. machine = "x86_64",
  122. release = "3.10.0-1160.21.1.el7.x86_64",
  123. sysname = "Linux",
  124. version = "#1 SMP Tue Mar 16 18:28:22 UTC 2021"
  125. } ~
  126. Parser/Features H L F I J
  127. - bash ? ? ? . ?
  128. - c ? ? ? ? ?
  129. - cpp ? ? ? ? ?
  130. - css ? . ? ? ?
  131. - go ? ? ? ? ?
  132. - gomod ? . . . ?
  133. - html ? ? ? ? ?
  134. - javascript ? ? ? ? ?
  135. - json ? ? ? ? .
  136. - jsonc ? ? ? ? ?
  137. - latex ? . ? . ?
  138. - lua ? ? ? ? ?
  139. - make ? . ? . ?
  140. - markdown ? . ? ? ?
  141. - markdown_inline ? . . . ?
  142. - python ? ? ? ? ?
  143. - query ? ? ? ? ?
  144. - rust ? ? ? ? ?
  145. - typescript ? ? ? ? ?
  146. - vim ? ? ? . ?
  147. - vimdoc ? . . . ?
  148. - vue ? . ? ? ?
  149. - yaml ? ? ? ? ?
  150. Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
  151. +) multiple parsers found, only one will be used
  152. x) errors found in the query, try to run :TSUpdate {lang} ~
  153. ==============================================================================
  154. provider: health#provider#check
  155. Clipboard (optional) ~
  156. - WARNING No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.
  157. - ADVICE:
  158. - :help |clipboard|
  159. Python 3 provider (optional) ~
  160. - Using: g:python3_host_prog = "python3"
  161. - Executable: /usr/bin/python3
  162. - ERROR Command error (job=16, exit code 1): `'/usr/bin/python3' -c 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)'` (in '/home/users/yunhai01/project/baidu/netdisk/p2p-sdk-mobile')
  163. stderr: Traceback (most recent call last): File "<string>", line 1, in <module>ModuleNotFoundError: No module named 'neovim'
  164. - Python version: 3.6.8
  165. - pynvim version: unable to load neovim Python module
  166. - ERROR pynvim is not installed.
  167. Error: unable to load neovim Python module
  168. - ADVICE:
  169. - Run in shell: /usr/bin/python3 -m pip install pynvim
  170. Python virtualenv ~
  171. - OK no $VIRTUAL_ENV
  172. Ruby provider (optional) ~
  173. - WARNING `ruby` and `gem` must be in $PATH.
  174. - ADVICE:
  175. - Install Ruby and verify that `ruby` and `gem` commands work.
  176. Node.js provider (optional) ~
  177. - Node.js: v16.18.1
  178. - WARNING Missing "neovim" npm (or yarn, pnpm) package.
  179. - ADVICE:
  180. - Run in shell: npm install -g neovim
  181. - Run in shell (if you use yarn): yarn global add neovim
  182. - Run in shell (if you use pnpm): pnpm install -g neovim
  183. - You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim
  184. Perl provider (optional) ~
  185. - WARNING Perl version is too old, 5.22+ required
  186. - ADVICE:
  187. - See :help |provider-perl| for more information.
  188. - You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim
  189. ==============================================================================
  190. rainbow-delimiters: require("rainbow-delimiters.health").check()
  191. Custom strategies ~
  192. - OK Valid custom default strategy.
  193. - OK Valid custom strategy for 'vim'.
  194. - OK Valid custom strategy for 'lua'.
  195. - OK Valid custom strategy for 'cpp'.
  196. - OK Valid custom strategy for 'vimdoc'.
  197. - OK Valid custom strategy for 'c'.
  198. Custom queries ~
  199. - OK Valid custom default query
  200. - OK Valid custom query for 'javascript'
  201. - OK Valid custom query for 'latex'
  202. Custom highlight groups ~
  203. - OK Highlight group 'RainbowDelimiterRed' defined.
  204. - OK Highlight group 'RainbowDelimiterOrange' defined.
  205. - OK Highlight group 'RainbowDelimiterYellow' defined.
  206. - OK Highlight group 'RainbowDelimiterGreen' defined.
  207. - OK Highlight group 'RainbowDelimiterBlue' defined.
  208. - OK Highlight group 'RainbowDelimiterCyan' defined.
  209. - OK Highlight group 'RainbowDelimiterViolet' defined.
  210. ==============================================================================
  211. telescope: require("telescope.health").check()
  212. Checking for required plugins ~
  213. - OK plenary installed.
  214. - OK nvim-treesitter installed.
  215. Checking external dependencies ~
  216. - OK rg: found ripgrep 13.0.0
  217. - OK fd: found fd 8.5.3
  218. ===== Installed extensions ===== ~
  219. Telescope Extension: `aerial` ~
  220. - No healthcheck provided
  221. Telescope Extension: `frecency` ~
  222. - OK nvim-web-devicons installed.
  223. - OK ripgrep installed.
  224. Telescope Extension: `fzf` ~
  225. - OK lib working as expected
  226. - OK file_sorter correctly configured
  227. - OK generic_sorter correctly configured
  228. Telescope Extension: `live_grep_args` ~
  229. - No healthcheck provided
  230. Telescope Extension: `notify` ~
  231. - No healthcheck provided
  232. Telescope Extension: `persisted` ~
  233. - No healthcheck provided
  234. Telescope Extension: `projects` ~
  235. - No healthcheck provided
  236. Telescope Extension: `undo` ~
  237. - No healthcheck provided
  238. Telescope Extension: `zoxide` ~
  239. - No healthcheck provided
  240. ==============================================================================
  241. vim.lsp: require("vim.lsp.health").check()
  242. - LSP log level : WARN
  243. - Log path: /home/users/yunhai01/.local/state/nvim/lsp.log
  244. - Log size: 54 KB
  245. vim.lsp: Active Clients ~
  246. - clangd (id=1, root_dir=/home/users/yunhai01/project/baidu/netdisk/p2p-sdk-mobile)
  247. - null-ls (id=2, root_dir=/home/users/yunhai01/project/baidu/netdisk/p2p-sdk-mobile/project/src)
  248. - copilot (id=3, root_dir=/home/users/yunhai01/project/baidu/netdisk/p2p-sdk-mobile/project/src)
  249. ==============================================================================
  250. vim.treesitter: require("vim.treesitter.health").check()
  251. - Nvim runtime ABI version: 14
  252. - OK Parser: bash ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/bash.so
  253. - OK Parser: c ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/c.so
  254. - OK Parser: cpp ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/cpp.so
  255. - OK Parser: css ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/css.so
  256. - OK Parser: go ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/go.so
  257. - OK Parser: gomod ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/gomod.so
  258. - OK Parser: html ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/html.so
  259. - OK Parser: javascript ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/javascript.so
  260. - OK Parser: json ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/json.so
  261. - OK Parser: jsonc ABI: 13, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/jsonc.so
  262. - OK Parser: latex ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/latex.so
  263. - OK Parser: lua ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/lua.so
  264. - OK Parser: make ABI: 13, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/make.so
  265. - OK Parser: markdown ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/markdown.so
  266. - OK Parser: markdown_inline ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/markdown_inline.so
  267. - OK Parser: python ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/python.so
  268. - OK Parser: rust ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/rust.so
  269. - OK Parser: typescript ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/typescript.so
  270. - OK Parser: vimdoc ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/vimdoc.so
  271. - OK Parser: vue ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/vue.so
  272. - OK Parser: yaml ABI: 14, path: /home/users/yunhai01/.local/share/nvim/site/lazy/nvim-treesitter/parser/yaml.so
  273. - OK Parser: c ABI: 14, path: /ext/tools/squashfs-root/usr/lib/nvim/parser/c.so
  274. - OK Parser: lua ABI: 14, path: /ext/tools/squashfs-root/usr/lib/nvim/parser/lua.so
  275. - OK Parser: query ABI: 14, path: /ext/tools/squashfs-root/usr/lib/nvim/parser/query.so
  276. - OK Parser: vim ABI: 14, path: /ext/tools/squashfs-root/usr/lib/nvim/parser/vim.so
  277. - OK Parser: vimdoc ABI: 14, path: /ext/tools/squashfs-root/usr/lib/nvim/parser/vimdoc.so
  278. ==============================================================================
  279. which-key: require("which-key.health").check()
  280. - ERROR Failed to run healthcheck for "which-key" plugin. Exception:
  281. function health#check, line 25
  282. Vim(eval):E5108: Error executing lua ...are/nvim/site/lazy/which-key.nvim/lua/which-key/keys.lua:406: Invalid buffer id: 97
  283. stack traceback:
  284. [C]: in function 'nvim_buf_get_keymap'
  285. ...are/nvim/site/lazy/which-key.nvim/lua/which-key/keys.lua:406: in function 'update_keymaps'
  286. ...e/nvim/site/lazy/which-key.nvim/lua/which-key/health.lua:15: in function 'check'
  287. [string "luaeval()"]:1: in main chunk

如果有插件工作不正常、老报警告框,可以通过自检发现一些问题。

主题

启动后默认的黑色背景看着黑乎乎的不够亮快,通过快捷键 (SPACE + f + c) 调出主题切换页:

这里选择 catppuccin-latte:

好多了。不过重启后就又恢复默认了,需要修改以下 lua 配置 (~/.config/nvim/lua/core/settings.lua):

  1. ...
  2. -- Set the colorscheme to use here.
  3. -- Available values are: `catppuccin`, `catppuccin-latte`, `catppucin-mocha`, `catppuccin-frappe`, `catppuccin-macchiato`.
  4. ---@type string
  5. settings["colorscheme"] = "catppuccin"
  6. -- Set it to true if your terminal has transparent background.
  7. ---@type boolean
  8. settings["transparent_background"] = false
  9. -- Set background color to use here.
  10. -- Useful if you would like to use a colorscheme that has a light and dark variant like `edge`.
  11. -- Valid values are: `dark`, `light`.
  12. ---@type "dark"|"light"
  13. settings["background"] = "dark"
  14. ...

本来是想改 colorscheme 选项的,后来发现有个 background = dark,尝试将这个改为 light 试试,重启后默认主题自动切换为 catppuccin-latte 了,下面是主题实时切换的效果:

2 核 CPU 切换有点费劲,毕竟是老旧机器,将就看吧~

状态栏

上一节中切换主题时,好多 scheme 套件的状态栏展示有问题,黑乎乎的一块显示不清楚,这是由于状态栏使用的插件 lualine 有自己的主题,需要单独设置,由于 lualine 属于插件,它们的配置文件位置稍有不同 (~/.config/nvim/lua/modules/configs/ui/lualine.lua):

  1. ...
  2. local function custom_theme()
  3. vim.api.nvim_create_autocmd("ColorScheme", {
  4. group = vim.api.nvim_create_augroup("LualineColorScheme", { clear = true }),
  5. pattern = "*",
  6. callback = function()
  7. has_catppuccin = vim.g.colors_name:find("catppuccin") ~= nil
  8. require("lualine").setup({ options = { theme = custom_theme() } })
  9. end,
  10. })
  11. ...

主要修改 require("lualine").setup 一行中 theme = 的值即可,可供选择的值参考这篇。从代码上看,对于 catppuccin-* 主题,会做状态栏的同步,所以相对要好一些,可以无脑选择。

目前 nvimdots 对老旧系统的支持已经不错了,早先我设置 blue 主题时,状态栏是这个样子:

根本没法看,通过设置 lualine 主题为 onenight 解决了这个问题:

目前已经不需要单独进行设置了。

快捷键

nvimdots 提供了很丰富的快捷键支持,一般都是三键组合,例如 <leader>+f+w 进入关键字搜索,其中 <leader> 是可定义的,目前默认为空格键。

通过 :verbose nmap 可以查看所有的键映射:

想看单独的键可以在后面增加参数,例如输入 :verbose nmap gD

常用的 gD、gd、gh、gf、gr、K 都有说明。自定义的键映射位于:~/.config/nvim/lua/core/mapping.lua

  1. local bind = require("keymap.bind")
  2. local map_cr = bind.map_cr
  3. local map_cu = bind.map_cu
  4. local map_cmd = bind.map_cmd
  5. local map_callback = bind.map_callback
  6. local core_map = {
  7. -- Suckless
  8. ["n|<S-Tab>"] = map_cr("normal za"):with_noremap():with_silent():with_desc("edit: Toggle code fold"),
  9. ["n|<C-s>"] = map_cu("write"):with_noremap():with_silent():with_desc("edit: Save file"),
  10. ["n|Y"] = map_cmd("y$"):with_desc("edit: Yank text to EOL"),
  11. ["n|D"] = map_cmd("d$"):with_desc("edit: Delete text to EOL"),
  12. ["n|n"] = map_cmd("nzzzv"):with_noremap():with_desc("edit: Next search result"),
  13. ["n|N"] = map_cmd("Nzzzv"):with_noremap():with_desc("edit: Prev search result"),
  14. ["n|J"] = map_cmd("mzJ`z"):with_noremap():with_desc("edit: Join next line"),
  15. ["n|<Esc>"] = map_callback(function()
  16. _flash_esc_or_noh()
  17. end)
  18. :with_noremap()
  19. :with_silent()
  20. :with_desc("edit: Clear search highlight"),
  21. ["n|<C-h>"] = map_cmd("<C-w>h"):with_noremap():with_desc("window: Focus left"),
  22. ["n|<C-l>"] = map_cmd("<C-w>l"):with_noremap():with_desc("window: Focus right"),
  23. ["n|<C-j>"] = map_cmd("<C-w>j"):with_noremap():with_desc("window: Focus down"),
  24. ["n|<C-k>"] = map_cmd("<C-w>k"):with_noremap():with_desc("window: Focus up"),
  25. ["t|<C-w>h"] = map_cmd("<Cmd>wincmd h<CR>"):with_silent():with_noremap():with_desc("window: Focus left"),
  26. ["t|<C-w>l"] = map_cmd("<Cmd>wincmd l<CR>"):with_silent():with_noremap():with_desc("window: Focus right"),
  27. ["t|<C-w>j"] = map_cmd("<Cmd>wincmd j<CR>"):with_silent():with_noremap():with_desc("window: Focus down"),
  28. ["t|<C-w>k"] = map_cmd("<Cmd>wincmd k<CR>"):with_silent():with_noremap():with_desc("window: Focus up"),
  29. ["n|<A-h>"] = map_cr("vertical resize -3"):with_silent():with_desc("window: Resize -3 vertically"),
  30. ["n|<A-l>"] = map_cr("vertical resize +3"):with_silent():with_desc("window: Resize +3 vertically"),
  31. ["n|<A-j>"] = map_cr("resize -3"):with_silent():with_desc("window: Resize -3 horizontally"),
  32. ["n|<A-k>"] = map_cr("resize +3"):with_silent():with_desc("window: Resize +3 horizontally"),
  33. ["n|<C-q>"] = map_cr("wq"):with_desc("edit: Save file and quit"),
  34. ["n|<A-S-q>"] = map_cr("q!"):with_desc("edit: Force quit"),
  35. ["n|<leader>o"] = map_cr("setlocal spell! spelllang=en_us"):with_desc("edit: Toggle spell check"),
  36. ["n|tn"] = map_cr("tabnew"):with_noremap():with_silent():with_desc("tab: Create a new tab"),
  37. ["n|tk"] = map_cr("tabnext"):with_noremap():with_silent():with_desc("tab: Move to next tab"),
  38. ["n|tj"] = map_cr("tabprevious"):with_noremap():with_silent():with_desc("tab: Move to previous tab"),
  39. ["n|to"] = map_cr("tabonly"):with_noremap():with_silent():with_desc("tab: Only keep current tab"),
  40. -- Insert mode
  41. ["i|<C-u>"] = map_cmd("<C-G>u<C-U>"):with_noremap():with_desc("edit: Delete previous block"),
  42. ["i|<C-b>"] = map_cmd("<Left>"):with_noremap():with_desc("edit: Move cursor to left"),
  43. ["i|<C-a>"] = map_cmd("<ESC>^i"):with_noremap():with_desc("edit: Move cursor to line start"),
  44. ["i|<C-s>"] = map_cmd("<Esc>:w<CR>"):with_desc("edit: Save file"),
  45. ["i|<C-q>"] = map_cmd("<Esc>:wq<CR>"):with_desc("edit: Save file and quit"),
  46. -- Command mode
  47. ["c|<C-b>"] = map_cmd("<Left>"):with_noremap():with_desc("edit: Left"),
  48. ["c|<C-f>"] = map_cmd("<Right>"):with_noremap():with_desc("edit: Right"),
  49. ["c|<C-a>"] = map_cmd("<Home>"):with_noremap():with_desc("edit: Home"),
  50. ["c|<C-e>"] = map_cmd("<End>"):with_noremap():with_desc("edit: End"),
  51. ["c|<C-d>"] = map_cmd("<Del>"):with_noremap():with_desc("edit: Delete"),
  52. ["c|<C-h>"] = map_cmd("<BS>"):with_noremap():with_desc("edit: Backspace"),
  53. ["c|<C-t>"] = map_cmd([[<C-R>=expand("%:p:h") . "/" <CR>]])
  54. :with_noremap()
  55. :with_desc("edit: Complete path of current file"),
  56. -- Visual mode
  57. ["v|J"] = map_cmd(":m '>+1<CR>gv=gv"):with_desc("edit: Move this line down"),
  58. ["v|K"] = map_cmd(":m '<-2<CR>gv=gv"):with_desc("edit: Move this line up"),
  59. ["v|<"] = map_cmd("<gv"):with_desc("edit: Decrease indent"),
  60. ["v|>"] = map_cmd(">gv"):with_desc("edit: Increase indent"),
  61. }
  62. bind.nvim_load_mapping(core_map)

这里有两个键是我之前用习惯的:Ctrl+j 向上移屏一行、Ctrl+k 向下移屏一行。vim 将这两个键映射到了 Ctrl+e 和 Ctrl+y,一直觉得用着不太顺手,可以手动添加:

  1. :nmap <C-j> <C-e>
  2. :nmap <C-k> <C-y>

然而重启 nvim 后就不起作用了。可以在上面的配置文件中加入以下内容实现永久修改:

  1. -- Move Up/Down
  2. ["n|<C-h>"] = map_cmd("<C-e>"),
  3. ["n|<C-l>"] = map_cmd("<C-y>"),
  4. ["n|<C-k>"] = map_cmd("<C-y>"):with_noremap(),
  5. ["n|<C-j>"] = map_cmd("<C-e>"):with_noremap(),

注意由于 Ctrl+h/j/k/l 已被 nvimdots 挪为它用,为防止热键冲突,需要将之前的注释掉:

  1. -- ["n|<C-h>"] = map_cmd("<C-w>h"):with_noremap():with_desc("window: Focus left"),
  2. -- ["n|<C-l>"] = map_cmd("<C-w>l"):with_noremap():with_desc("window: Focus right"),
  3. -- ["n|<C-j>"] = map_cmd("<C-w>j"):with_noremap():with_desc("window: Focus down"),
  4. -- ["n|<C-k>"] = map_cmd("<C-w>k"):with_noremap():with_desc("window: Focus up"),

看起来是用于窗口切换 (Ctrl+w+h/j/k/l) 了,感觉没啥必要。注意看 Ctrl+j 与 Ctrl+h、Ctrl+k 与 Ctrl+l 只相差了一个 :with_noremap(),这个能起什么作用?看下面这个演示就清楚了:

加了了 :with_noremap() 的,会上下滑动多行,实现按更少的键的目的。

PS:目前在新版本的 nvimdots 上,新增的键还是不起作用,目前还没有精力研究,回头研究通了再更新一波~

编程语言支持

相比于主流的 IDE 只能支持若干编程语言,neovim+nvimdots 搭建的 IDE 更加强大,可以轻松支持几十种语言,是冷门语言开发者的福音。输入 :LspInfo 查看已安装的语言服务:

这是 nvimdots 的默认配置,可以通过修改配置文件来增加或删除语言服务 (~/.config/nvim/lua/core/settings.lua):

  1. ...
  2. -- Set the language servers that will be installed during bootstrap here.
  3. -- check the below link for all the supported LSPs:
  4. -- https://github.com/neovim/nvim-lspconfig/tree/master/lua/lspconfig/server_configurations
  5. ---@type string[]
  6. settings["lsp_deps"] = {
  7. "bashls",
  8. "clangd",
  9. "html",
  10. "jsonls",
  11. "lua_ls",
  12. "pylsp",
  13. "gopls",
  14. }
  15. -- Set the general-purpose servers that will be installed during bootstrap here.
  16. -- Check the below link for all supported sources.
  17. -- in `code_actions`, `completion`, `diagnostics`, `formatting`, `hover` folders:
  18. -- https://github.com/nvimtools/none-ls.nvim/tree/main/lua/null-ls/builtins
  19. ---@type string[]
  20. settings["null_ls_deps"] = {
  21. "clang_format",
  22. "gofumpt",
  23. "goimports",
  24. "prettier",
  25. "shfmt",
  26. "stylua",
  27. "vint",
  28. }
  29. -- Set the Debug Adapter Protocol (DAP) clients that will be installed and configured during bootstrap here.
  30. -- Check the below link for all supported DAPs:
  31. -- https://github.com/jay-babu/mason-nvim-dap.nvim/blob/main/lua/mason-nvim-dap/mappings/source.lua
  32. ---@type string[]
  33. settings["dap_deps"] = {
  34. "codelldb", -- C-Family
  35. "delve", -- Go
  36. "python", -- Python (debugpy)
  37. }
  38. ...

主要就是修改 lsp_deps 数组了。例如对于不需要且没有安装成功的 pylsp 和 gopls,直接删除之。重启 nvim 后,不再报烦人的警告了。

另外 checkhealth 中也有 tree-sitter 支持的语言列表:

  1. Parser/Features H L F I J
  2. - bash ? ? ? . ?
  3. - c ? ? ? ? ?
  4. - cpp ? ? ? ? ?
  5. - css ? . ? ? ?
  6. - go ? ? ? ? ?
  7. - gomod ? . . . ?
  8. - html ? ? ? ? ?
  9. - javascript ? ? ? ? ?
  10. - json ? ? ? ? .
  11. - jsonc ? ? ? ? ?
  12. - latex ? . ? . ?
  13. - lua ? ? ? ? ?
  14. - make ? . ? . ?
  15. - markdown ? . ? ? ?
  16. - markdown_inline ? . . . ?
  17. - python ? ? ? ? ?
  18. - query ? ? ? ? ?
  19. - rust ? ? ? ? ?
  20. - typescript ? ? ? ? ?
  21. - vim ? ? ? . ?
  22. - vimdoc ? . . . ?
  23. - vue ? . ? ? ?
  24. - yaml ? ? ? ? ?
  25. Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
  26. +) multiple parsers found, only one will be used
  27. x) errors found in the query, try to run :TSUpdate {lang} ~

每列为一个功能点,每行为一种语言,全打勾表示所有功能在线。

保存时美化

各种 formatter 设置好了不用岂不可惜,所以 nvimdots 默认的行为是关闭文件自动使用对应语言的 formatter 进行格式美化。然而在浏览第三方库文件或其它开源库代码时,这么做就有点画蛇添足了,通过 FormatToggle 可以关闭默认选项,然而重启 nvim 后又会自动打开,因此需要修改配置文件 (~/.config/nvim/lua/core/settings.lua):

  1. ...
  2. -- Set it to false if there are no need to format on save.
  3. ---@type boolean
  4. settings["format_on_save"] = true
  5. -- Set it to false if the notification after formatting is annoying.
  6. ---@type boolean
  7. settings["format_notify"] = true
  8. -- Set it to true if you prefer formatting ONLY the *changed lines* as defined by your version control system.
  9. -- NOTE: This entry will only be respected if:
  10. -- > The buffer to be formatted is under version control (Git or Mercurial);
  11. -- > Any of the server attached to that buffer supports |DocumentRangeFormattingProvider| server capability.
  12. -- Otherwise Neovim would fall back to format the whole buffer, and a warning will be issued.
  13. ---@type boolean
  14. settings["format_modifications_only"] = false
  15. -- Set the format disabled directories here, files under these dirs won't be formatted on save.
  16. --- NOTE: Directories may contain regular expressions (grammar: vim). |regexp|
  17. --- NOTE: Directories are automatically normalized. |vim.fs.normalize()|
  18. ---@type string[]
  19. settings["format_disabled_dirs"] = {
  20. -- Example
  21. "~/format_disabled_dir",
  22. }
  23. ...

format_on_save 改为 false 即可。

效果

至此基于 neovim 的 IDE 就搭建完成了,在正式开始演试之前,需要为 efm-langserver 插件生成一份代码编译清单:compile_commands.json。

compile_commands

这个文件的内容是实际传递给编译器的命令行,包括各种参数:

  1. ...
  2. {
  3. "directory": "/ext/code/transmission/build/libtransmission",
  4. "command": "/opt/compiler/gcc-8.2/bin/g++ -DCURL_STATICLIB -DFMT_EXCEPTIONS=0 -DFMT_HEADER_ONLY=1 -DHAVE_FALLOCATE64 -DHAVE_FLOCK -DHAVE_GETMNTENT -DHAVE_GETTEXT -DHAVE_LIBINTL_H -DHAVE_MKDTEMP -DHAVE_NGETTEXT -DHAVE_POSIX_FADVISE -DHAVE_POSIX_FALLOCATE -DHAVE_PREAD -DHAVE_PWRITE -DHAVE_SENDFILE64 -DHAVE_SO_REUSEPORT=1 -DHAVE_STATVFS -DHAVE_SYS_STATVFS_H -DHAVE_XLOCALE_H -DMINIUPNP_STATICLIB -DNATPMP_STATICLIB -DPACKAGE_DATA_DIR=\\\"/usr/local/share\\\" -DPOSIX -DSYSTEM_MINIUPNP -DWIDE_INTEGER_DISABLE_FLOAT_INTEROP -DWIDE_INTEGER_DISABLE_IOSTREAM -DWITH_INOTIFY -DWITH_UTP -D__TRANSMISSION__ -I/ext/code/transmission/build/libtransmission -I/ext/code/transmission/third-party/libutp/include -I/ext/code/transmission/third-party/libb64/include -I/ext/code/transmission/third-party/jsonsl -I/ext/code/transmission/third-party/wildmat -isystem /ext/code/transmission/build/third-party/libdeflate.bld/pfx/include -isystem /usr/local/include -isystem /ext/code/transmission/cmake/../third-party/fast_float/include -isystem /ext/code/transmission/build/third-party/libpsl.bld/pfx/include -isystem /ext/code/transmission/build/third-party/libnatpmp.bld/pfx/include -isystem /ext/code/transmission/build/third-party/miniupnpc.bld/pfx/include -isystem /ext/code/transmission/build/third-party/dht.bld/pfx/include -isystem /ext/code/transmission/cmake/../third-party/utfcpp/source -isystem /ext/code/transmission/cmake/../third-party/wide-integer -isystem /ext/code/transmission/cmake/../third-party/fmt/include -isystem /ext/code/transmission/build/third-party/libevent.bld/pfx/include -O3 -DNDEBUG -fPIC -W -Wall -Wextra -Wcast-align -Wduplicated-cond -Wextra-semi -Wfloat-equal -Winit-self -Wint-in-bool-context -Wlogical-op -Wmissing-format-attribute -Wnull-dereference -Wpointer-arith -Wredundant-decls -Wrestrict -Wshadow -Wsign-compare -Wsuggest-override -Wuninitialized -Wunreachable-code -Wunused -Wunused-const-variable -Wunused-parameter -Wunused-result -Wwrite-strings -std=gnu++17 -o CMakeFiles/transmission.dir/session.cc.o -c /ext/code/transmission/libtransmission/session.cc",
  5. "file": "/ext/code/transmission/libtransmission/session.cc"
  6. },
  7. ...

如此,efm-langserver 等语言服务,就能借助这里的信息,更好的理解代码,例如哪些预处理中的代码是生效的,从而更好的实现符号跳转与补全等功能。这类清单也用于 ccls、VSCode 等 IDE 中,并不是 efm-langserver 专属的。一般项目本身并不包含这类清单,需要单独生成一下,下面分项目类型分别介绍。

  • cmake:cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 .
  • make:bear make
  • Android NDK
    • ndk-build GEN_COMPILE_COMMANDS_DB=true
    • bear ndk-build
  • ninja:ninja -f out/combined-kona.ninja -t compdb | tee ./compile_commands.json
  • ...

cmake、ninja 支持的比较好,NDK 算 make 的一种,也有自己的选项可以设置,对于最原始的 make,只能借助于 bear 命令了,另外 ndk-build 也可以基于这种方式生成。

bear

bear 是一个用来生成包含编译时选项的数据库的工具。 通常它将输出文件 compile_commands.json ,可以供给例如 vscode 中的 Microsoft C/C++ 插件或者 vim 中的 YouCompleteMe 插件使用,让插件可以正确的解析当前 C++ 源文件的各种依赖信息,例如头文件包含路径。

在 CentOS 上默认没有这个命令,需要安装一下,默认的 yum 源没有,需要源码安装:

  1. wget https://github.com/rizsotto/Bear/archive/refs/tags/2.4.4.zip
  2. unzip 2.4.4.zip
  3. cd Bear-2.4.4
  4. mkdir build; cd build
  5. cmake ..
  6. make
  7. sudo make install

安装过程也比较简单,CentOS7 适合老一点的版本,2.4.4 实测可用。

transmission

下面用一个 BitTorrent 网络传输方面很知名的开源库 tranmission 从头到尾做个测试。

  1. git clone --recurse-submodules git@github.com:firedgirl/transmission.git transmission
  2. cd transmission
  3. git checkout -b 4.0.x origin/4.0.x
  4. mkdir build; cd build
  5. cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 -DCMAKE_CXX_COMPILER=/opt/compiler/gcc-8.2/bin/g++ -DCMAKE_C_COMPILER=/opt/compiler/gcc-8.2/bin/gcc -DCMAKE_CXX_FLAGS="-Wl,-rpath,/opt/compiler/gcc-8.2/lib64 -I /usr/local/include" -DCMAKE_BUILD_TYPE=Release ..
  6. make -j8

注意添加到 cmake 中的 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 选项,他的作用和 bear 是一致的。项目编译完成后,将在根目录生成一个 compile_commands.json 文件,内容比较多就不展示了,感兴趣的可以看这个链接

将它移动到项目根目录,打开 neovim,就可以像 VSCode 一样浏览啦。上面的 transmission 只是一个例子,可以更换为任意 c/c++ 开源库。有的平台不支持 compile_commands.json 的生成,此时符号跳转就没那么准了,不过文件内的一些函数定义跳转还是支持的。

功能展示

自动补全

这里演示的是成员变量与成员函数,其它像普通变量、函数调用什么的也都能自动补全。

字符串查找

Telescope 插件,底层基于 fzf & rg,快捷键 SPACE + f + w 调出。缺点有以下几点

  • 多次查询一个关键字不便,需要每次输入关键词且从头开始遍历
  • 跳转到某个文件再查找,会局限查找范围为文件当前所在目录

对于第二个问题,在老版本上通过修改配置可以修复,具体修改 ~/.config/nvim/lua/core/event.lua:

  1. { "BufEnter", "*", "silent! lcd %:p:h" },

将上面这行注释掉即可。但是目前新版本,这个配置不见了,目前还没有抽出精力来研究。

符号跳转

上图演示了几种典型的跳转场景:

  • gD:声明、调用点跳转定义
  • K:提示定义
  • gd:小窗显示定义

除了 c++ 中的虚函数都能比较好的进行处理,虚函数由于是运行时才能确定调用哪个实现,这里跳不过去也情有可原,但是如果能将备选的实现列出来让用户自己选择,就更好了。

上面的动图,展示的是 gh 命令查找所有调用点,在弹出的浮窗中,右侧按文件列出所有调用点,进入文件下面每个调用点时,左侧可以预览,回车时跳转到调用点。大部分时间可用,有时一些符号找不到,就得使用之前的字符串查找了。

h/cpp 文件切换

ClangdSwitchSourceHeaderVSplit,基于 clangd,快捷键 SPACE + h 调出,同级别的还可以使用 ClangdSwitchSourceHeader & ClangdSwitchSourceHeaderSplit,前者直接替换当前 buffer,后者是横向分屏,可以让 SPACE + h 指向其中任何一个,看个人偏好。头文件可以不必和 cpp 在同一个目录,这个插件一样可以找到。

后记

第一次入坑  neovm + nvimdots 是 2022.11 的事情了,最近有新机器了又在 2024.07 搞了一次,发现nvimdots 有很大更新,以至于之前的一些快捷键、UI 发生了变化,一些移植经验也已经不适用了,虽然一度很懵逼,但这是一件好事,说明 neovim + 基于 lua 的插件配置正在蓬勃发展,现在写出来的文字,可能过一两年又面目全非了。总归来说,现在这条路是对的,比那些还在坚守 vim + gtags + cscope + YouCompleteMe… 老路的要强大太多了,现在网上这方面的资料,远远跟不上开源社区的进步速度,毫不夸张的说,关于 vim 搭建现代化 IDE 的文章,只要超过五年以上,就是老古董了,除非研究技术发展历史,否则没必要深究。

基于 lua 的 neovim 配置还有很多,nvimdots 只是其中的一个,其实他们采用的基础插件是相通的,像 Lazy、Mason、Lsp 等等,这种项目像一个粘合剂,将各种零散的小插件整合在一起,达到用户开箱即用的效果,免去了很多插件搜索的过程,各位有使用的好的项目,也可以在留言区分享哈~

关于 nvimdots 的任何使用问题都可以在 Issue 页面提问,之前我在这里提的一些问题,很快就有人回复,一些不错的建议还得到了采纳,成就感满满!总之,除了一帮子中国人在那飙英文有点受不了,其它都还好??。

参考

[1]. Linux(Ubuntu/CentOS) 下查看 GLIBC 版本

[2]. 升级glibc至2.18

[3]. 通过ipaddress更新github的hostsIP

[4]. Can one set std=c99 in GCC as a default? [duplicate]

[5]. yum安装指定版本软件包

[6]. The Cargo Book

[7]. 5分钟搞懂用户空间文件系统FUSE工作原理

[8]. ayamir/nvimdots

[9]. Neovim 代码高亮插件 nvim-treesitter 的安装与配置

[10]. lazy-nvim插件管理器基础入门

[11]. neovim入门指南(一):基础配置

[12]. 我的现代化Neovim配置

[13]. 详解nvim内建LSP体系与基于nvim-cmp的代码补全体系

[14]. CentOS7 使用脚本安装后插件一直报下载失败 #326

[15]. CentOS7 安装后 scheme 无法保存

[16]. gd/D 不能跳转到定义

[17]. change theme can't change status line theme

[18]. how to disable FormatOnSave permanently?

[19]. How can I map C-j to C-e in lua

[20]. 生成compile_commands.json文件

[21]. Android C++ 生成 compile_commands.json

[22]. Bear 2.4.4 精简版

[23]. How can I traverse functions with jump list?

 

原文链接:https://www.cnblogs.com/goodcitizen/p/18197750/build_development_environment_for_cpp_on_old_linux_by_neovim

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号