Created
September 9, 2020 06:32
-
-
Save yzdann/45ab0175bdca7524e6059cde7f1a68c8 to your computer and use it in GitHub Desktop.
Revisions
-
adembudak revised this gist
Sep 4, 2020 . 1 changed file with 26 additions and 24 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,9 +1,10 @@ - [Intro](#intro) * [Problem](#problem) * [Solution](#solution) - [Setup](#setup) * [A server](#a-server) * [A client](#a-client) * [compile_commands.json file generation](#compile-commandsjson-file-generation) - [Linting](#linting) - [Code formatting](#code-formatting) @@ -13,8 +14,8 @@ ## Intro I want to share how I use Vim as C++ development environment, adding things like code completion, linting, formatting and snippet support. If you come from the IDE land and have been set your options with the checkbox on a GUI, you might need a mental shift to use text based configuration tools, like Vim. ### Problem @@ -24,7 +25,7 @@ successful, some others evolved, yet others deprecated. I tried plugins like YouCompleteMe, they were great but the process that making them work wasn't a pleasant experience. Creating a completion engine admittedly hard, porting those code to other editors without touching implementation details is virtually impossible. ### Solution @@ -71,7 +72,7 @@ apt-get install -qq clang-11 clang-tools-11 clang-11-doc libclang-common-11-dev ``` ... and that's it. Now along with the clangd, I have the latest stable C++ compiler, standard library implementation (that I can enjoy latest features added to the language), a linter and a code formatter. We got the server, what about the client? ### A client @@ -88,7 +89,7 @@ apt-get install npm To add the coc.nvim and other plugins in easy way, a plugin manager required. Again, various options are available, I'll use [vim-plug](https://github.com/junegunn/vim-plug): `.vim/vimrc`: ``` call plug#begin('~/.vim/plugged') @@ -100,9 +101,9 @@ Plug 'neoclide/coc.nvim', {'for':['zig','cmake','rust', call plug#end() ``` This is from my vimrc file. Plugins are listed between `plug#begin` and `plug#end` as `Plug 'Github_URI_path'`. It allows plugins work with certain filetype, which listed after `for`. I don't need and want this plugin to work other with filetypes, like .txt, .md etc. `:PlugInstall` will install and `:PlugUpdate` update the plugins. A common ritual among the vimmers, once plugin installed, reading its doc. Usually available with `:help pluginName`. @@ -133,14 +134,13 @@ now, I'll just register language server and leave others default: "--all-scopes-completion", "--background-index", "--clang-tidy", "--cross-file-rename", "--completion-parse=always", "--completion-style=detailed", "--function-arg-placeholders", "--header-insertion-decorators", "--query-driver=/usr/bin/**/clang-*,/home/adem/GCC-10/bin/g++*", "--header-insertion=never", "--limit-results=0", "-j=6", "--pch-storage=memory", @@ -152,7 +152,7 @@ now, I'll just register language server and leave others default: This calls clangd with the parameters listed on args array. Check out all options of clangd with `clangd --help`. You can add any number of server to `languageserver` object. That way you can have same editing experience, mapping, theme, etc for different languages on the same editor: ``` { @@ -194,20 +194,20 @@ command. ## Linting The [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) linter can be called via clangd. A linter is a tool that shouts out the fishy parts of the code. Make sure passed `--clang-tidy` arg to clangd on coc-setting.json file. You can enable some family of checks, and dump it into a file: ``` clang-tidy --checks='-*,bugprone-*' --dump-config > .clang-tidy ``` Clangd will detect this file and lint your code based on some criteria. See all checks with: `clang-tidy --list-checks` ## Code formatting People used [AStyle](http://astyle.sourceforge.net) and some other tools to format their code. As a millennial, my first encounter with such a tool happen with [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It's fairly easy to use: @@ -218,7 +218,7 @@ clang-format -i source.cpp [vim-clang-format](https://github.com/rhysd/vim-clang-format) plugin allows us to use clang-format in automatized way, like formatting on every save: `.vim/vimrc`: ``` " between plug#begin/plug#end Plug 'rhysd/vim-clang-format', {'for' : ['c', 'cpp']} @@ -232,12 +232,13 @@ Snippets are kind of underappreciated helpers. They reduce repetitive, no-brainer jobs. Install coc.nvim snippet extension: `:CocInstall coc-snippets` Let extension know where to find snippets: `.vim/coc-settings.json`: ```shell "snippets.textmateSnippetsRoots": ["/home/adem/.config/snippets"], ``` On daily coding, when I type `cmake`, it extends to: ``` cmake_minimum_required(VERSION |) @@ -249,7 +250,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ``` where each `|` waiting to be typed. Writing such a snippet is pretty easy. Just like in VSCode, it's a JSON file: `/home/adem/.config/snippets/cmake.json`: ``` @@ -284,14 +285,15 @@ this. Here is an example mapping: ``` nnoremap <F5> :SCCompileRunAF -g -Wall -Wextra -std=c++2a<cr> ``` When I press `<F5>`, it compiles and run the executable. More on `:h SingleCompile` --- This client-server architecture in mind, you can use similar setup on other platforms. In Windows, you can get Windows binaries of LLVM and use clangd on VSCode with [clangd extension](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd). On Emacs, there is a [lsp mode](https://github.com/emacs-lsp/lsp-mode) support. Feel free to embarrass me what I made with this post :) Thanks for reading. -
adembudak created this gist
Sep 3, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,298 @@ - [Intro](#intro) * [Problem](#problem) * [Solution](#solution) - [Setup](#setup) * [Server](#server) * [Client](#client) * [compile_commands.json file generation](#compile-commandsjson-file-generation) - [Linting](#linting) - [Code formatting](#code-formatting) - [Snippets](#snippets) - [One shot compilations](#one-shot-compilations) ## Intro I want to share how I use Vim as C++ development environment, adding things like code completion, linting, formatting, snippet. If you come from the IDE land and have been set your options with the checks box on a GUI, you might need mental shift to use text based configuration tools, like Vim. ### Problem There has been plugins to provide IDE-like features to Vim. Some of them were successful, some others evolved, yet others deprecated. I tried plugins like YouCompleteMe, they were great but the process that making them work wasn't a pleasant experience. Creating a completion engine admittedly hard, porting those code other editors without touching implementation details is virtually impossible. ### Solution [The language server protocol](https://microsoft.github.io/language-server-protocol) developed solve this problem. The idea is, create a set of rule and implement a server and a client that follows the rules, then communicate over the protocol and provide functionalities like auto complete, go-to definition, search function calls, diagnostics. Quoting from its [website](https://langserver.org): > LSP creates the opportunity to reduce the m-times-n complexity problem of > providing a high level of support for any programming language in any editor, > IDE, or client endpoint to a simpler m-plus-n problem. ## Setup The *server* needs to installed on the host system, and *client* needs to provided by the editor, either as a plugin or build-in. In Vim, it must be a plugin, NeoVim has an [experimental support](https://github.com/neovim/nvim-lspconfig). Some IDEs, like CLion, ship both out of package... with a price. ### A server There are two actively developed language servers for C++: [clangd](https://clangd.llvm.org/) and [ccls](https://github.com/MaskRay/ccls). Both are great. I found clangd is somewhat easier to install. Precompiled binaries are available in [here](https://releases.llvm.org/download.html). APT packages also available at [https://apt.llvm.org](https://apt.llvm.org). On my fresh installed Debian 10, I just use: ```bash apt-add-repository 'deb http://apt.llvm.org/buster/ llvm-toolchain-buster-11 main' wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add - apt-get update apt-get install -qq clang-11 clang-tools-11 clang-11-doc libclang-common-11-dev \ libclang-11-dev libclang1-11 clang-format-11 clangd-11 clang-tidy-11 \ libc++-11-dev libc++abi-11-dev ``` ... and that's it. Now along with the clangd, I have the latest stable C++ compiler, standard library implementation (that I can enjoy latest features added to language), a linter and a code formatter. We got the server, what about the client? ### A client To make use of clangd, we'll need a language client. [Various](https://langserver.org) implementations are available, I'll use [coc.nvim](https://github.com/neoclide/coc.nvim/). It's written in [TypeScript](https://www.typescriptlang.org) needs [Node.js](https://nodejs.org/en) runtime: ``` apt-get install npm ``` To add the coc.nvim and other plugins in easy way, a plugin manager required. Again, various options are available, I'll use [vim-plug](https://github.com/junegunn/vim-plug): `.vimrc`: ``` call plug#begin('~/.vim/plugged') Plug 'neoclide/coc.nvim', {'for':['zig','cmake','rust', \'java','json', 'haskell', 'ts','sh', 'cs', \'yaml', 'c', 'cpp', 'd', 'go', \'python', 'dart', 'javascript', 'vim'], 'branch': 'release'} call plug#end() ``` This is from my .vimrc file. Plugins are listed between `plug#begin` and `plug#end` as `Plug 'Github_URI_path'`. It allows plugins work with certain filetype, which listed after `for`. I don't need and want this plugin to work other filetypes, like .txt, .md etc. `:PlugInstall` will install and `:PlugUpdate` update the plugins. A common ritual among the vimmers, once plugin installed, reading its doc. Usually available with `:help pluginName`. coc.nvim holds server configurations in a JSON file called `coc-settings.json` (with `:CocConfig`). You can customize almost everything the way server behave. Check out full scheme from [here](https://github.com/neoclide/coc.nvim/blob/master/data/schema.json). For now, I'll just register language server and leave others default: `.vim/coc-settings.json`: ``` { "languageserver":{ "clangd":{ "command":"clangd", "filetypes":[ "c", "cpp" ], "rootPatterns":[ "compile_commands.json", ".git" ], "args":[ "--compile-commands-dir=build", "--compile_args_from=filesystem", "--all-scopes-completion", "--background-index", "--clang-tidy", "--completion-parse=always", "--completion-style=detailed", "--cross-file-rename", "--function-arg-placeholders", "--header-insertion-decorators", "--query-driver=/usr/bin/**/clang-*,/home/adem/GCC-10/bin/g++*", "--header-insertion=never", "--cross-file-rename", "--limit-results=0", "-j=6", "--pch-storage=memory", ] } } } ``` This calls clangd with the parameters listed on args array. Check out all options of clangd with `clangd --help`. You can add any number of server to `languageserver` object, that way you can have same editing experience, mapping, theme, etc for different languages on the same editor: ``` { "languageserver":{ "clangd":{ // clangd options }, "rls" { // rls options }, "bash-lsp" { // bash-lsp options } } } ``` For mappings (a term used for reassignable shortcuts in Vim), begin with the [example configuration](https://github.com/neoclide/coc.nvim/#example-vim-configuration). If you want to take a look, this idiot holds [his configurations](https://github.com/p1v0t/dotfiles) on Github. Now got the server and client, but need one more thing. ## compile_commands.json file generation The last part of the ceremony involves using [CMake](https://cmake.org). All we need is, adding a single line definition on toplevel CMakeLists.txt: ``` set(CMAKE_EXPORT_COMPILE_COMMANDS ON) ``` This generates a file called [compile_commands.json](https://clang.llvm.org/docs/JSONCompilationDatabase.html) on build directory. It contains include paths, compiler command and options. These helps clangd to figure out what is where. If the project don't use CMake, but make, you can use [Bear](https://github.com/rizsotto/Bear) to generate this file with `bear make` command. ## Linting The [clang-tidy](https://clang.llvm.org/extra/clang-tidy/) linting tool can be called via clangd. A linter is a tool that shout out the fishy parts of the code. Make sure passed `--clang-tidy` arg to clangd on coc-setting.json file. You can enable some family of checks, and dump it into a file: ``` clang-tidy --checks='-*,bugprone-*' --dump-config > .clang-tidy; ``` Clangd will detect this file and lint your code based on some criteria. See all checks with: `clang-tidy --list-checks` ## Code formatting People used [aspell](http://aspell.net) and some other tools to format their code, As a millennial, my first encounter with such a tool happen with [clang-format](https://clang.llvm.org/docs/ClangFormat.html). It's fairly easy to use: ``` clang-format -i source.cpp ``` [vim-clang-format](https://github.com/rhysd/vim-clang-format) plugin allows us to use clang-format in automatized way, like formatting on every save: `vimrc`: ``` " between plug#begin/plug#end Plug 'rhysd/vim-clang-format', {'for' : ['c', 'cpp']} let g:clang_format#auto_format=1 ``` ## Snippets Snippets are kind of underappreciated helpers. They reduce repetitive, no-brainer jobs. Install coc.nvim snippet extension: `:CocInstall coc-snippets` Let extension know where to find snippets: `coc-settings.json`: ```shell "snippets.textmateSnippetsRoots": ["/home/adem/.config/snippets"], ``` On daily configurations when I type `cmake` it extends to: ``` cmake_minimum_required(VERSION |) DESCRIPTION "|" HOMEPAGE_URL https://github.com/p1v0t/ | LANGUAGES CXX) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) | ``` where each `|` waiting to be typed. Writing such a snippet is pretty easy. Just like in VSCode, it's JSON file: `/home/adem/.config/snippets/cmake.json`: ``` { "cmake": { "prefix": [ "cmake" ], "body": [ "cmake_minimum_required(VERSION ${1:version})", "", "project(${2:projname}", "DESCRIPTION \"${3:description}\"", "HOMEPAGE_URL https://github.com/p1v0t/${4:reponame}", "LANGUAGES CXX)", "", "set(CMAKE_EXPORT_COMPILE_COMMANDS ON)", "${0}" ] } } ``` There is also [an extension](https://github.com/voldikss/coc-cmake) for CMake which provides basic completion. See list of extensions in [here](https://github.com/neoclide). ## One shot compilations If you like to write small programs and don't need to build, [SingleCompile](https://github.com/vim-scripts/SingleCompile) plugin is just for this. Here is an example mapping: ``` nnoremap <F5> :SCCompileRunAF -g -Wall -Wextra -std=c++2a<cr> ``` When I press <F5>, it compiles and run the executable. More on `:h SingleCompile` --- This client-server architecture in mind, you can use similar setup on other platforms. In Windows, you can install get Windows binaries from LLVM and use clangd with VSCode with [clangd extension](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd). On Emacs, there is a [lsp mode](https://github.com/emacs-lsp/lsp-mode) support. Feel free to embarrass me what I made with this post :) Thanks for reading. ---