..
  Copyright (C)  2023  Jeremie Salvi.
  Permission is granted to copy, distribute and/or modify this document
  under the terms of the GNU Free Documentation License, Version 1.3
  or any later version published by the Free Software Foundation;
  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
  A copy of the license is included in the section entitled "GNU
  Free Documentation License".

Création d'un environnement vscodium
====================================

Le but ici va être d'automatiser un maximum d'actions, comme par exemple la compilation, le débug,
tout en les intégrant dans vscodium. Nous allons aussi configurer l'autocomplétion, la navigation
dans les fonctions et les librairies, et tout ce qui peut rendre notre IDE plus ergonomique.

Je vais essayer de maintenir cette section à jour au fur et à mesure que j'améliore
le projet.

.. warning:: pensez à importer les variables d'environnement avec esp_idf_import
  comme vu dans l'installation si nécessaire.

Créer un nouveau project
------------------------

On commence par créer un projet a l'aide le l'utilitaire IDF :

.. code-block:: bash

  idf.py create-project new_project

On peut ensuite ouvrir vscodium et ouvrir ce dossier ``Ctrl+O`` ou ``File -> Open Folder``.


Déclarer le $PATH et les variables d'environnement pour le terminal
-------------------------------------------------------------------

Si on lance notre terminal vscode et qu'on fait un ``export``, on ne retrouve pas les variables
d'environnement nécessaires à bon fonctionnement des outils IDF. Pour cela, il faut les renseigner
dans notre espace de travail.

Pour cela, on fait ``F1`` et on cherche settings.json.

.. image:: ../images/esp32/settings.json.png
  :width: 600

Il va nous ouvrir le fichier ``.vscode/settings.json`` qui va contenir nos paramètres
propre au projet. Dans celui ci, on va renseigner toutes les variables d'environnement 
qu'on à après un ``esp_idf_import`` comme vu dans la partie 
`installation </esp32/installation.html#installation-et-configuration-de-l-esp-idf>`_.

On ajoute les lignes suivantes :

.. code-block:: json
  :linenos:

  {
    "C_Cpp.intelliSenseEngine": "Tag Parser",
    "terminal.integrated.cwd": "/root/test/new_project",
    // environnement variables needeed by ESP_IDF
    "terminal.integrated.env.linux": {
      "ESP_IDF_VERSION": "5.1",
      "ESP_ROM_ELF_DIR": "/opt/esp/esp-idf/.espressif/tools/esp-rom-elfs/20220823/",
      "IDF_DEACTIVATE_FILE_PATH": "/tmp/tmpxj9n6nndidf_46523",
      "IDF_PATH": "/opt/esp/esp-idf",
      "IDF_PYTHON_ENV_PATH": "/opt/esp/esp-idf/.espressif/python_env/idf5.1_py3.10_env",
      "IDF_TOOLS_EXPORT_CMD": "/opt/esp/esp-idf/export.sh",
      "IDF_TOOLS_INSTALL_CMD": "/opt/esp/esp-idf/install.sh",
      "IDF_TOOLS_PATH": "/opt/esp/esp-idf/.espressif",
      "OPENOCD_SCRIPTS": "/opt/esp/esp-idf/.espressif/tools/openocd-esp32/v0.11.0-esp32-20221026/openocd-esp32/share/openocd/scripts",
      "PATH": "/opt/esp/esp-idf/components/esptool_py/esptool:/opt/esp/esp-idf/components/espcoredump:/opt/esp/esp-idf/components/partition_table:/opt/esp/esp-idf/components/app_update:/opt/esp/esp-idf/.espressif/tools/xtensa-esp-elf-gdb/12.1_20221002/xtensa-esp-elf-gdb/bin:/opt/esp/esp-idf/.espressif/tools/xtensa-esp32-elf/esp-2022r1-11.2.0/xtensa-esp32-elf/bin:/opt/esp/esp-idf/.espressif/tools/esp32ulp-elf/2.35_20220830/esp32ulp-elf/bin:/opt/esp/esp-idf/.espressif/tools/openocd-esp32/v0.11.0-esp32-20221026/openocd-esp32/bin:/opt/esp/esp-idf/.espressif/python_env/idf5.1_py3.10_env/bin:/opt/esp/esp-idf/tools:/usr/local/sbin:/usr/local/bin:/usr/bin"
    },
  }

Configuration de l'extension C/C++
----------------------------------

Commencons par un simple code pour vérifier que tout fonctionne : 

.. code-block:: c
  :linenos:

  #include <stdio.h>
  #include <esp_log.h>
  #include <freertos/FreeRTOS.h>
  #include <freertos/task.h>

  void app_main(void)
  {
    int count=0;
    while (true)
    {
      ESP_LOGI("NEW PROJECT", "my first test %d", count++);
      vTaskDelay(pdMS_TO_TICKS(1000));
    }
  }

On teste notre code avec les commandes suivantes :

.. code-block:: bash
  :linenos:

  idf.py set-target esp32
  idf.py build
  idf.py flash
  idf.py monitor

Pour quitter le moniteur, il suffit d'un ``Ctrl+]``.

Ok, une fois que tout marche, on peut quitter le terminal.
On voit que vscodium affiche des erreurs au niveau des include qu'il ne trouve pas. Réglons tout ça.

En appuyant sur ``F1`` et en cherchant ``C/C++ configuration`` on trouve soit l'interface utilisateur soit un
racourci pour créer et renseigner le fichier ``.vscode/c_cpp_properties.json``.
Pour que la recherche intelligente foncrionne, il faut configurer l'extension pour qu'elle
sache ou chercher les librairies fournies par l'IDE. Des templates sont déjà disponibles
sur `le github d'espressif <https://github.com/espressif/vscode-esp-idf-extension/tree/master/templates/.vscode>`_.


.. image:: ../images/esp32/c_cpp_config.png
  :width: 600

En m'inspirant de ce qu'esperssif fournit pour son extension vscodium,
voilà à quoi je suis arrivé pour que tout fonctionne bien :

.. code-block:: json
  :linenos:

  {
    "configurations": [
      {
        "name": "ESP_IDF",
        "includePath": [
          "${workspaceFolder}/**",
          "/opt/esp/esp-idf/components/**",
          "/opt/esp/esp-idf/.espressif/tools/**"
        ],
        "defines": [],
        "compilerPath": "",
        "cStandard": "c11",
        "cppStandard": "c++17",
        "intelliSenseMode": "linux-gcc-x64",
        "browse": {
          "path": [
            "${workspaceFolder}/**",
            "/opt/esp/esp-idf/components/**",
            "/opt/esp/esp-idf/.espressif/tools/**"
          ],
          "limitSymbolsToIncludedHeaders": false
        }
      }
    ],
    "version": 4
  }

Voilà, ça c'est pour que vscode et intellisense trouvent toutes les ressources dont ils ont besoin.


Configurer des tâches
---------------------

C'est ici, à mon sens, la fonctionnalié qui donne le plus de confort et qui va nous faire gagner un temps précieux.
Dans vscodium, on peut définir des tâches personnalisées pour le projet en cours, et les executer rapidement avec un raccourci clavier.

Dans un premier temps, je créer un script dans ``.scripts/tasks.sh`` que je rend executable, et dans lequel je vais coder toutes les actions
que je vais répéter souvent, comme builder le code, flasher l'esp, lancer QEMU pour débuger, etc. Voici le code, il est améliorable bien
entendu et on va y rajouter toutes les fonctionnalités que nous voudrons par la suite.

.. code-block:: bash
  :linenos:

  #!/bin/bash

  function kill_idf {
    for i in $(ps -elf | grep 'idf.py' | awk '{print $4}')
    do
      echo "found process $i"
      kill $i
    done
  }

  function build {
    $IDF_PATH/tools/idf.py build
  }

  function flash {
    kill_idf

    $IDF_PATH/tools/idf.py flash
    exit 0
  }

  function monitor {
    kill_idf
    $IDF_PATH/tools/idf.py monitor
    exit 0
  }


  #######################
  # Main
  #######################

  case $1 in
    kill_idf)
      echo "Killing all idf process"
      kill_idf
      ;;
    build)
      echo "Building project"
      build
      ;;
    flash)
      echo "Flashing memory"
      flash
      ;;
    monitor)
      echo "Monitoring output"
      monitor
      ;;
    *)
      echo "Missing args"
      exit 1
      ;;
  esac 

Voilà, une fois ce script fait, on va y assigner des tâches vscodium. Je vais aller vite sur les explications, je
vous met un lien vers `la documentation officielle du fichier tasks.json <https://code.visualstudio.com/docs/editor/tasks>`_.

On créer un fichier ``.vscode/tasks.json`` et on y renseigne le code suivant :

.. code-block:: json
  :linenos:

  {
    "version": "2.0.0",
    "tasks": [
      {
        "label": "kill idf.py process",
        "type": "shell",
        "command": "${workspaceFolder}/.scripts/tasks.sh",
        "args": [
          "kill_idf"
        ],
        "presentation": {
          "reveal": "always",
          "panel": "shared",
          "close": false
        },
        "problemMatcher": []
      },
      {
        "label": "build project",
        "type": "shell",
        "command": "${workspaceFolder}/.scripts/tasks.sh",
        "args": [
          "build"
        ],
        "presentation": {
          "reveal": "always",
          "panel": "shared",
          "close": false
        },
        "problemMatcher": []
      },
      {
        "label": "flash esp memory",
        "type": "shell",
        "command": "${workspaceFolder}/.scripts/tasks.sh",
        "args": [
          "flash"
        ],
        "presentation": {
          "reveal": "always",
          "panel": "shared",
          "close": false
        },
        "problemMatcher": []
      },
      {
        "label": "monitor",
        "type": "shell",
        "command": "${workspaceFolder}/.scripts/tasks.sh",
        "args": [
          "monitor"
        ],
        "presentation": {
          "reveal": "always",
          "panel": "new",
          "close": true
        },
        "problemMatcher": []
      },
      {
        "label": "build, flash, and monitor",
        "dependsOrder": "sequence",
        "dependsOn": ["build project", "flash esp memory", "monitor"],
        "problemMatcher": []
      },
    ]
  }

Et voilà, comme vous pouvez le voir, vous avez toutes les tâches de compilation, execution, et debug imtégrées à
vscodium. on peut y accéder en tappant ``F1 -> run task``, et pour gagner du temps, on peut même définir un raccourci clavier
Pour gagner encore une étape.

.. image:: ../images/esp32/run_tasks.png
  :width: 600

Et voilà, un appui sur ``Ctrl+F1`` me donne accès à autant de tâches que je voidrai en créer.

.. image:: ../images/esp32/tasks.png
  :width: 600
