Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion integration/ide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Desktop IDEs
codeblocks
eclipse
emacs
neovim
netbeans
qtcreator
sublimetext
Expand All @@ -55,4 +56,4 @@ Cloud IDEs

cloud9
codeanywhere
eclipseche
eclipseche
200 changes: 200 additions & 0 deletions integration/ide/neovim.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
.. Copyright (c) 2014-present PlatformIO <contact@platformio.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

.. _ide_neovim:

Neovim
======

`Neovim <https://neovim.io/>`_ is a powerful, open-source and configurable text
editor based on `Vim <http://www.vim.org/>`_. Neovim is designed for use both from a command-line interface and as a
standalone application in a graphical user interface.

.. image:: ../../_static/images/ide/neovim/ide-platformio-neovim.png

.. contents::

Project Generation
------------------

1. Open system Terminal and install :ref:`piocore` if you haven't already
2. Create new folder for your project and change directory (``cd``) to it
3. Generate a project using PlatformIO Core Project Generator

Choose board ``ID`` using :ref:`cmd_boards` or `Embedded Boards Explorer <https://platformio.org/boards>`_
command and generate project via the following command:

.. code-block:: shell

pio project init --board <ID>


Language Server
---------------

IDE features like completion, diagnostics and navigation are provided by language servers like clangd or ccls.
When cross compiling for embedded architectures, language servers require some metadata to understand target architecture, system include paths and libraries.
This metadata can be generated by PlatformIO.

Neovim supports LSP (Language Server Protocol) natively.
Language Servers can be installed manually or using Mason.
You can configure and enable them using ``vim.lsp.config()`` and ``vim.lsp.enable()``.


clangd
^^^^^^

Install `clangd <https://clangd.llvm.org/installation>`_ via Mason or install manually ensuring it is in your ``PATH``

You must launch clangd with the option ``--query-driver``.
This is an allowlist that tells clangd which paths it is allowed to query a compiler in.
Often clangd executes the compiler itself with some options,
then the output is parsed to get target architecture and system include directories.
This greatly improves support for embedded GCC toolchains.
Since this executes arbitrary binaries, you should only whitelist directories that you trust.

``--query-driver=<string>`` - Comma separated list of globs for white-listing gcc-compatible drivers that are safe to execute. Drivers matching any of these globs will be used to extract system includes. e.g. ``/usr/bin/**/clang-*,/path/to/repo/**/g++-*``

.. code-block:: lua

local clangd_allowlist = {
vim.env.HOME .. '/.platformio/packages/toolchain-*/bin/*',
'/usr/bin/*', -- if you want to allow all compilers installed here
-- you can add other compiler directories here
}

---@type vim.lsp.Config
local clangd_config = {
cmd = {
'clangd',
'--query-driver=' .. table.concat(clangd_allowlist, ','),
},

reuse_client = function(client, config)
-- Neovim runs this function to decide whether an existing lsp client can be reused when you open a new buffer
-- you can add custom logic here for when to actually reuse client instead of spawning a new one
-- for example, only reuse client when working in PlatformIO projects containing platformio.ini
--
-- By default, Neovim reuses client if name and root_dir matches
-- but when jumping into headers located outside the project, that isnt true
-- so here we are always using the same client to keep the context from compile_commands.json
-- for setups containing multiple unrelated C/C++ project you may want to add project specific logic instead
return true
end,

-- you can configure other options for clangd here
}

vim.lsp.config('clangd', clangd_config)
vim.lsp.enable('clangd')

Generate ``compile_commands.json`` in project root directory

.. code-block:: shell

pio run -t compiledb

.. warning::
You should regenerate ``compile_commands.json`` (using the above command) whenever:

1. Opening a project for the first time (either after generation by you or after cloning from a git repo or by any other means)
2. A new library is added in the project
3. A new source file is created in the project (not always necessary, but recommended)

``compile_commands.json`` contains the exact compiler command that gets used when building.
Clangd may not recognize some GCC flags, and some additional flags may be required.

For this you may also want to create a ``.clangd`` file.
It is a ``YAML`` file that you can use to add or remove flags, and configure other project specific settings

For example: if you are getting errors similar to the following in Neovim

.. code-block::

Diagnostics:
1. Unknown argument '-mlongcalls'; did you mean '-mlong-calls'? [drv_unknown_argument_with_suggestion]
2. Unknown argument: '-fstrict-volatile-bitfields' [drv_unknown_argument]
3. Unknown argument: '-fno-tree-switch-conversion' [drv_unknown_argument]

Create a ``.clangd`` file in the project root directory with the flags that are giving you errors

.. code-block:: yaml

CompileFlags:
Remove:
- "-mlongcalls"
- "-fstrict-volatile-bitfields"
- "-fno-tree-switch-conversion"

.. note::
1. This only removes clangd errors in the editor. The compiler command during build is unaffected.
2. You can also create ``~/.config/clangd/config.yaml`` which sets global clangd defaults for all projects

See Clangd and Neovim documentation for more information:

- `Clangd System Headers <https://clangd.llvm.org/guides/system-headers>`_ and the section ``Query-driver``
- `Clangd Compile Commands <https://clangd.llvm.org/design/compile-commands>`_ and the section ``Query-driver``
- `Clangd Configuration <https://clangd.llvm.org/config#compileflags>`_ and the section ``CompileFlags``
- `Clangd Editor Plugins <https://clangd.llvm.org/installation#editor-plugins>`_
- `Neovim LSP <https://neovim.io/doc/user/lsp/#lsp-core>`_


ccls
^^^^

Manually install `ccls <https://github.com/MaskRay/ccls/>`_ and make sure it is in your ``PATH`` or install via Mason if available. Then configure and enable the ``ccls`` server in your Neovim config:

.. code-block:: lua

---@type vim.lsp.Config
local ccls_config = {
filetypes = { 'c', 'cpp', 'objc', 'objcpp', 'cuda', 'h' },
-- you can configure other options for the ccls server here
}

vim.lsp.config('ccls', ccls_config)
vim.lsp.enable('ccls')

Generate ``.ccls`` in project root directory

.. code-block:: shell

pio project init --ide vim

.. warning::
You should regenerate ``.ccls`` (using the above command) whenever:

1. Opening a project for the first time (either after generation by you or after cloning from a git repo or by any other means)
2. A new library is added in the project
3. A new source file is created in the project (not always necessary, but recommended)


Useful Commands
---------------

Build (without uploading)

.. code-block:: shell

pio run

Build and Upload (if no error)

.. code-block:: shell

pio run --target upload

Serial Monitor

.. code-block:: shell

pio device monitor -b <baud rate>

3 changes: 2 additions & 1 deletion redirects.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
/ide/eclipse.html -> /integration/ide/eclipse.html
/ide/eclipseche.html -> /integration/ide/eclipseche.html
/ide/emacs.html -> /integration/ide/emacs.html
/ide/neovim.html -> /integration/ide/neovim.html
/ide/netbeans.html -> /integration/ide/netbeans.html
/ide/pioide.html -> /integration/ide/pioide.html
/ide/qtcreator.html -> /integration/ide/qtcreator.html
Expand Down Expand Up @@ -114,4 +115,4 @@
/userguide/remote/cmd_run.html -> /core/userguide/remote/cmd_run.html
/userguide/remote/cmd_test.html -> /core/userguide/remote/cmd_test.html
/userguide/remote/cmd_update.html -> /core/userguide/remote/cmd_update.html
/userguide/remote/index.html -> /core/userguide/remote/index.html
/userguide/remote/index.html -> /core/userguide/remote/index.html