.. index:: Visual Studio Code, IDE; Visual Studio Code

******************
Visual Studio Code
******************

`Visual Studio Code <https://code.visualstudio.com/>`_ is a
lightweight but powerful source code editor which runs on multiple
platforms.

With the `C/C++ for Visual Studio Code extension
<https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools/>`_
it is possible to use Calypsi in Visual Studio Code.

This works as Visual Studio Code can be tailored to use different
build and debugger tools. The most crucial part is perhaps the
debugger integration which is based on the MI (Machine Interface),
which is also what the Calypsi debugger supports.

Visual Studio Code is a good choice for a graphical user interface to
Calypsi as it is very actively developed, lightweight, responsive
and highly configurable.

Documenting the full Visual Studio Code is beyond the scope of this
guide. Refer to the official `Visual Studio Code documentation
<https://code.visualstudio.com/docs>`_ for detailed information.

Some basics on how to get started is covered here as it may not work
entirely as you may expect from traditional IDEs.

.. image:: images/vscode-session.png
   :width: 90%


Installation
============

Installation is easy to do by downloading it from the official
site. You can easily update it inside Visual Studio Code itself.


Project setup
=============

In contrast to many IDEs you will not find any project setup in the
menus.

To create a new project from scratch, use ``File>Open`` and create a
new folder for your project and then press ``Open``. You now have an empty
project directory.

If you have an existing project, you can just select ``File>Open`` and
browse to the top folder in that project, the press ``Open`` and you
have loaded your project.

Project specific files are kept in an ``.vscode`` directory in your
project directory. Initially there are no such files.


Building
--------

Once you have populated your project and perhaps created a
``Makefile``, you can add a task to build it.
Select ``Tasks>Configure Tasks...`` and pick
``Create tasks.json file from template``. Then select ``Others``
to get a ``tasks.json`` that you can edit. It may end up looking
something like:

.. code-block:: json

  {
      "version": "0.2.0",
      "tasks": [
          {
              "label": "build",
              "type": "shell",
              "command": "make -k",
              "options": {
                  "cwd": "${workspaceRoot}/src"
              },
              "problemMatcher": [
                  "$gcc"
              ]
          }
      ]
  }


Here we tell it that we want to run ``make -k`` in the ``src``
sub-directory and match error output to something that looks
like what ``gcc`` would produce.


Debugging
---------

To start the debugger you need to add a launch configuration.

.. code-block:: json

  {
      "version": "0.2.0",
      "configurations": [
          {
              "name": "C++ Launch",
              "type": "cppdbg",
              "request": "launch",
              "program": "${workspaceRoot}/src/myproject",
              "args": [],
              "stopAtEntry": false,
              "cwd": "${workspaceRoot}/src",
              "environment": [],
              "externalConsole": true,
              "logging": {
                  "trace": true,
                  "traceResponse": true,
                  "engineLogging":true
              },
              "linux": {
                  "MIMode": "lldb"
              },
              "osx": {
                  "MIMode": "lldb",
                  "miDebuggerPath": "dbnut",
                  "launchCompleteCommand": "exec-run",
                  "setupCommands": [
                      {
                          "text": "module insert /Users/me/projects/modules41/41cx.mod",
                          "description": "load mainframe",
                          "ignoreFailures": false
                      }
                  ]
              },
              "windows": {
                  "MIMode": "gdb"
              }
          },
      ]
  }

There are a couple of things to specify here.

#. We need to specify that we are using ``dbnut`` as the debugger using
   ``miDebuggerPath``

#. We also need to tell that we want to use ``lldb`` as ``MIMode`` [#MI]_

#. We also need to load the calculator firmware. Here it is done using
   ``setupCommands`` that invokes the debugger console command
   ``module insert``.

.. rubric:: Footnotes
.. [#MI] Even though ``dbnut`` is much closer to ``gdb`` than ``lldb``
         at the command level, we need to specify ``lldb`` as the MI
         mode. The reason is that in the ``gdb`` mode, Visual
         Studio Code works around a bug on UNIX style platforms for
         the MI command ``-exec-interrupt`` (which interrupts
         execution).
         The work around is it to send a signal to a real UNIX
         process to interrupt it. As we are running in a simulation
         environment the process is not a normal UNIX process and
         cannot be interrupted that way.
         Instead we use the ``lldb`` mode where MI command
         ``-exec-interrupt`` works properly, just as it does with
         ``dbnut``.

         Reference https://sourceware.org/bugzilla/show_bug.cgi?id=20035
