Calculated default value for a variable
============================================

.. objectives:: Objectives

   In this section we will reuse the value of a variable for the default value of another variable.
   
   We will first build the `https_proxy` family which will be used to illustrate this functionality.
     
.. prerequisites:: Prerequisites

    - We assume that Rougail's library is :ref:`installed <installation>` on your computer.

    - It is possible to retrieve the current state of the various Rougail files manipulated in this tutorial step
      by checking out the corresponding tag of the `rougail-tutorials` git repository.
      Each tag corresponds to a stage of progress in the tutorial.
      Of course, you can also decide to copy/paste or download the tutorial files contents while following the tutorial steps.

    If you want to follow this tutorial with the help of the corresponding :tutorial:`rougail-tutorials git repository <src/branch/1.1>`, 
    this workshop page corresponds to the tags :tutorial:`v1.1_040 <src/tag/v1.1_040/README.md>` to :tutorial:`v1.1_041 <src/tag/v1.1_041/README.md>` 
    in the repository.

    ::
   
       git clone https://forge.cloud.silique.fr/stove/rougail-tutorials.git
       git switch --detach v1.1_040

HTTPS family 
-------------

We have split the definition of the `manual` family into two specific files, 
the :file:`10-manual.yml` and the :file:`20-manual.yml` structure file: 

.. raw:: html
   :class: output 
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/tag/v1.1_040/tree.html 

..
    <p>
    <a href="https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/v1.1_040/./">.</a><br/>
	    └── <a href="https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/v1.1_040/./firefox/">firefox</a><br/>
	        ├── <a href="https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/v1.1_040/./firefox/00-proxy.yml">00-proxy.yml</a><br/>
	        ├── <a href="https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/v1.1_040/./firefox/10-manual.yml">10-manual.yml</a><br/>
	        └── <a href="https://forge.cloud.silique.fr/stove/rougail-tutorials/src/commit/v1.1_040/./firefox/20-manual.yml">20-manual.yml</a><br/>
    <br/><br/></p>

We will continue to complete the :file:`20-manual.yml` structure file, 
with variables entirely equivalent to those found in the `http_proxy` family from the :file:`10-manual.yml` structure file.
Until now, we only had the `use_for_https` :ref:`boolean variable in this structure file <tutorial_boolean_variable>`.
Now we are going to define an address and a port in the `https_proxy` family:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_040/firefox/20-manual.yml
   :linenos:
   :language: yaml
   :caption: The updated `manual` family in the :file:`firefox/20-manual.yml` structure file with the `https_proxy` family.

..
    %YAML 1.2
    ---
    version: 1.1

    manual:

      use_for_https: true  # Also use this proxy for HTTPS

      https_proxy:  # HTTPS Proxy

        address:
          description: HTTPS address
          type: domainname
          params:
            allow_ip: true

        port:
          description: HTTPS Port
          type: port
          default: 8080

.. _tutorial_calc_variable:

A default value calculated from another variable
--------------------------------------------------

.. type-along:: For those who follow the tutorial with the help of the git repository

    Now you need to checkout the :tutorial:`v1.1_041 <src/tag/v1.1_041/README.md>` version::
     
          git switch --detach v1.1_041

.. discussion:: A contextualized default value 

   A contextualized default value is a default value that changes according to the overall context of the configuration.
   A contextualized default value can come from, as we see here, a copy of the value of another variable.

The dynamic setting of a default value can be expressed this way: the default value is a pointer to another variable's value.
Here, the defaut value of `manual.https_proxy.address` points to the value of `manual.http_proxy.address`.

This is the same thing for the default value of the `manual.https_proxy.port` variable, 
which points to the `manual.http_proxy.port` value.

.. note:: In the following we will see that the `manual.https_proxy.address` type is `domainname`. 
          Indeed, this `domainname` type comes from the type of the variable it points to.

Reminder: here is the HTTP :file:`firefox/10-manual.yml` structure file: 

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_041/firefox/10-manual.yml
   :linenos:
   :language: yaml
   :caption: The :file:`firefox/10-manual.yml` structure file with the `http_proxy` family and the `disabled` property

..
  %YAML 1.2
    ---
    version: 1.1

    manual:  # Manual proxy configuration

      http_proxy:  # HTTP Proxy

        address:
          description: HTTP address
          type: domainname
          params:
            allow_ip: true

        port:
          description: HTTP Port
          type: port
          default: 8080
    ...


And here is the :file:`firefox/20-manual.yml` structure file where the calculated default values are:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_041/firefox/20-manual.yml   
   :linenos:
   :language: yaml
   :caption: The :file:`firefox/20-manual.yml` structure file with the `hidden` property on the `https_proxy` family.
   
..
    %YAML 1.2
    ---
    version: 1.1

    manual:

      use_for_https: true  # Also use this proxy for HTTPS

      https_proxy:  # HTTPS Proxy

        address:
          description: HTTPS address
          default:
            variable: __.http_proxy.address

        port:
          description: HTTPS Port
          default:
            variable: __.http_proxy.port
    ...

We can see here that the `address` variable's default value is conditionned by the `__.http_proxy.address` variable's value. 
The target variable is `manual.http_proxy.address`. 

.. seealso:: The `__.` is a :term:`relative path` notation and means the parent path of the current subfamily path.
          
          In the python quasi algorithmic notation we could say that:  
          
          .. code-block:: python
          
              __.http_proxy.address == http_proxy.address
              
          This is true only because in our use case `http_proxy.address` is located
          in the same `manual` subfamiliy than `https_proxy.address`.
          
          Have a look at the :ref:`variablepath` page for more details.


We then say that the `manual.https_proxy.address` and the `manual.https_proxy.port` default values are *calculated*.

.. glossary::

   calculated
   
        We say that a variable's value or a default variable's value is calculated 
        when there is a pointer which refers to another variable's value.
       
        :ref:`Other types of calculations exists <calculated_variable>`, in which this type of behavior does not occur 
        (the "pointer" behavior, notably type copying). 

The other types of calculation we will be explained later in this tutorial.

We're going to load some :term:`user data <user data>` to see what happens:

.. extinclude:: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_041/config/01/config.yml
   :linenos:
   :language: yaml
   :caption: The :file:`config/01/config.yml` user data
   
.. 
    ---
    proxy_mode: Manual proxy configuration
    manual:
      http_proxy:
        address: http.proxy.net
        port: 3128
      use_for_https: false
      https_proxy:
        address: https.proxy.net

Let's launch the Rougail CLI on it: 

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_041/config/01/cmd_ro.txt
   :class: terminal 
   
.. 
    rougail -m firefox/ -u yaml -yf config/01/config.yml

We have this result: 

.. raw:: html
   :url: https://forge.cloud.silique.fr/stove/rougail-tutorials/raw/commit/v1.1_041/config/01/output_ro.html
   :class: output 

..
    <pre>╭────────────── Caption ───────────────╮
    │ Variable <span style="color: #ffd700">Default value</span>               │
    │          <span style="color: #00aa00">Modified value</span>              │
    │          (⏳ Original default value) │
    ╰──────────────────────────────────────╯
    Variables:
    <span style="color: #5c5cff">┣━━ </span>📓 proxy_mode (Configure Proxy Access to the Internet): <span style="color: #00aa00">Manual proxy </span>
    <span style="color: #5c5cff">┃   </span><span style="color: #00aa00">configuration</span> ◀ loaded from the YAML file "config/01/config.yml" (⏳ No 
    <span style="color: #5c5cff">┃   </span>proxy)
    <span style="color: #5c5cff">┗━━ </span>📂 manual (Manual proxy configuration)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┣━━ </span>📂 http_proxy (HTTP Proxy)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span><span style="color: #5c5cff">┣━━ </span>📓 address (HTTP address): <span style="color: #00aa00">http.proxy.net</span> ◀ loaded from the YAML 
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span><span style="color: #5c5cff">┃   </span>file "config/01/config.yml"
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span><span style="color: #5c5cff">┗━━ </span>📓 port (HTTP Port): <span style="color: #00aa00">3128</span> ◀ loaded from the YAML file 
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span><span style="color: #5c5cff">    </span>"config/01/config.yml" (⏳ 8080)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┣━━ </span>📓 use_for_https (Also use this proxy for HTTPS): <span style="color: #00aa00">false</span> ◀ loaded from 
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span>the YAML file "config/01/config.yml" (⏳ true)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">┗━━ </span>📂 https_proxy (HTTPS Proxy)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">    </span><span style="color: #5c5cff">┣━━ </span>📓 address (HTTPS address): <span style="color: #00aa00">https.proxy.net</span> ◀ loaded from the YAML 
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">    </span><span style="color: #5c5cff">┃   </span>file "config/01/config.yml" (⏳ http.proxy.net)
    <span style="color: #5c5cff">    </span><span style="color: #5c5cff">    </span><span style="color: #5c5cff">┗━━ </span>📓 port (HTTPS Port): <span style="color: #ffd700">3128</span>
    </pre>

Notice that the default value is not changed when some values are settled from the :term:`user data file <user data>`.

The `https_proxy` variable's value is indeed modified, but the default value is still a calculated value (so the default value is indeed the value of the variable `http_proxy.address`, i.e., `"http.proxy.net"`), while the value defined by the user is `https.proxy.net`.

With the standard output of the Rougail CLI, the terminal display output, we can see the default value of the variable.

By interpreting the results of this standard output, we can see that even if a value has been assigned to this variable
(meaning the default value is not used) the variable's default value is not changed, but rather its actual value.

.. keypoints:: Key points progress

    **summary**

    We have learned how to set the default value of the `https_proxy.address` variable 
    with the value of the `http_proxy.address` variable. We did the same 
    `https_proxy.port` and the `https_proxy.port` variables.
    
    **notation**
    
    We have learned a notation very usefull for the subfamilies traversal: 

    - the `_.` notation means the current path of the family you're currently in
    - the `__.` notation means the parent path of the current subfamily path.

    Have a look at the :ref:`variablepath` page for more details.

