# Introduction

Ce didacticiel est destiné aux utilisateurs maîtrisant la programmation en C ou C++, ainsi que l'architecture de la Simple Virtual Machine.

Dans ce didacticiel, vous allez apprendre à ajouter de l'aide aux extensions.

Le temps de lecture de ce didacticiel est estimé à 25 minutes.

# Mise en place

Pour commencer, créez le canevas de l'extension dans le fichier aide.svm_plugin en utilisant ce code :

    PLUGIN help

    DEFINE

    OPTION help.prefix -p STR

    TYPE help.type
    %{
    	std::string _s;
    %}
    delete default: %{}

    INSTRUCTION help.new STR -> help.type
    %{
    	auto rs = ARGV_VALUE(0,string);
    	auto s = RAW_STRING(rs);
    	SVM_Value_String p = ::svm_plugin_get_option(svm,CONST_PEP(help,prefix));
    	if(not ::svm_value_state_is_null(svm,p))
    	{
    		auto rp = ::svm_value_string_get(svm,p);
    		s = RAW_STRING(rp)+s;
    	}
    	return NEW_PLUGIN(help,type,new type_type { s });
    %}

# Aide générale

Pour commencer, générez et compilez cette extension. Puis dans le terminal, lancez la commande depuis le répertoire où a été générée l'extension :

    man ./doc/svm_plugin_help.man

Le générateur d'extension a généré une page d'aide, certes incomplète, pour aider les développeurs d'applications Simple Virtual Machine à utiliser l'extension.

La première chose à faire pour compléter l'aide est de fournir une idée générale de ce que fait l'extension.

Modifiez le code de l'extension :

    PLUGIN help

    synopsis:
    %{
    This plugin handles a useless type.
    %}

    description:
    %{
    This plugin allows an application to create a type containing a string with an optional prefix.
    .P
    This prefix is configured by an option at application level.
    %}

    DEFINE

    OPTION help.prefix -p STR

    TYPE help.type
    %{
    	std::string _s;
    %}
    delete default: %{}

    INSTRUCTION help.new STR -> help.type
    %{
    	auto rs = ARGV_VALUE(0,string);
    	auto s = RAW_STRING(rs);
    	SVM_Value_String p = ::svm_plugin_get_option(svm,CONST_PEP(help,prefix));
    	if(not ::svm_value_state_is_null(svm,p))
    	{
    		auto rp = ::svm_value_string_get(svm,p);
    		s = RAW_STRING(rp)+s;
    	}
    	return NEW_PLUGIN(help,type,new type_type { s });
    %}

Générez à nouveau l'extension et rouvrez la page de manuel. Cette fois, des sections synopsis et description indiquent ce que réalise l'extension :

1. La section synopsis est en général une ligne d'accroche qui permet d'un coup d'œil de savoir à quoi l'extension sert.
2. La section description est quant à elle plus vaste, et précise comment fonctionne l'extension dans son ensemble.

Notez que le texte contenu dans les blocs d'aide sont des extraits de page de manuel, écrits en groff. Référez vous à la documentation de cet outil pour de plus amples détails sur sa syntaxe.

- Le générateur d'extension crée une page de manuel pour l'extension.
- Cette page de manuel peut être enrichie via les directives `synopsis` pour indiquer en une ligne à quoi l'extension sert, et `description` pour donner tous les détails nécessaires à une utilisation correcte de l'extension.

# Exemples

Parfois, quelques exemples d'utilisation d'une extension facilitent beaucoup la compréhension des utilisateurs.

Modifiez le code de l'extension :

    PLUGIN help

    synopsis:
    %{
    This plugin handles a useless type.
    %}

    description:
    %{
    This plugin allows an application to create a type containing a string with an optional prefix.
    .P
    This prefix is configured by an option at application level.
    %}

    example: "Basic usage"
    %{
    .nf
    #!/usr/bin/env svm
    LOG
    MACHINE PLUGIN "===PLUGINMACHINELIB==="
    PROCESS "example"
    	CODE "main" INLINE
    		:memory help.type/t
    		:help.new "value" -> &t
    	END
    END
    .fi
    %}

    example: "With prefix"
    %{
    .nf
    #!/usr/bin/env svm
    LOG
    MACHINE PLUGIN "===PLUGINMACHINELIB===" -p "prefix-"
    PROCESS "example"
    	CODE "main" INLINE
    		:memory help.type/t
    		:help.new "value" -> &t
    	END
    END
    .fi
    %}

    DEFINE

    OPTION help.prefix -p STR

    TYPE help.type
    %{
    	std::string _s;
    %}
    delete default: %{}

    INSTRUCTION help.new STR -> help.type
    %{
    	auto rs = ARGV_VALUE(0,string);
    	auto s = RAW_STRING(rs);
    	SVM_Value_String p = ::svm_plugin_get_option(svm,CONST_PEP(help,prefix));
    	if(not ::svm_value_state_is_null(svm,p))
    	{
    		auto rp = ::svm_value_string_get(svm,p);
    		s = RAW_STRING(rp)+s;
    	}
    	return NEW_PLUGIN(help,type,new type_type { s });
    %}

Générez à nouveau l'extension et rouvrez la page de manuel. Cette fois, à la fin de la page apparaissent des exemples de code.

Un fichier source d'extension peut contenir plusieurs exemples, qui ont chacun :

1. une chaine entre double-quotes servant de titre à l'exemple,
2. un bloc en groff (notez les balises .nf et .fi pour délimiter un bloc non formatté) qui contient l'exemple. La chaine `===PLUGINMACHINELIB===` sera ici remplacée par le chemin vers l'extension lorque celle-ci sera installée avec autotools.

- L'aide peut être agrémentée d'exemples de code utilisant l'extension.
- Il peut y avoir plusieurs exemples dans un fichier d'extension, indiqués par la directive `example` suivie d'un titre et du texte de l'exemple.

# Objets

Dans les pages d'aide générées, les objets définis par l'extension sont listés avec un texte générique indiquant que l'aide n'est pas disponible pour ces objets.

Modifiez le code de l'extension :

    PLUGIN help

    synopsis:
    %{
    This plugin handles a useless type.
    %}

    description:
    %{
    This plugin allows an application to create a type containing a string with an optional prefix.
    .P
    This prefix is configured by an option at application level.
    %}

    example: "Basic usage"
    %{
    .nf
    #!/usr/bin/env svm
    LOG
    MACHINE PLUGIN "===PLUGINMACHINELIB==="
    PROCESS "example"
    	CODE "main" INLINE
    		:memory help.type/t
    		:help.new "value" -> &t
    	END
    END
    .fi
    %}

    example: "With prefix"
    %{
    .nf
    #!/usr/bin/env svm
    LOG
    MACHINE PLUGIN "===PLUGINMACHINELIB===" -p "prefix-"
    PROCESS "example"
    	CODE "main" INLINE
    		:memory help.type/t
    		:help.new "value" -> &t
    	END
    END
    .fi
    %}

    DEFINE

    OPTION help.prefix -p STR
    help: "This option specifies the prefix to add to all values of the useless type."

    TYPE help.type
    %{
    	std::string _s;
    %}
    delete default: %{}
    help:
    %{
    This type is the useless type.
    .P
    It contains only a string and has to operation defined, to ensure it is completely useless.
    %}

    INSTRUCTION help.new STR -> help.type
    %{
    	auto rs = ARGV_VALUE(0,string);
    	auto s = RAW_STRING(rs);
    	SVM_Value_String p = ::svm_plugin_get_option(svm,CONST_PEP(help,prefix));
    	if(not ::svm_value_state_is_null(svm,p))
    	{
    		auto rp = ::svm_value_string_get(svm,p);
    		s = RAW_STRING(rp)+s;
    	}
    	return NEW_PLUGIN(help,type,new type_type { s });
    %}
    help:
    %{
    This instruction creates an instance of the useless type.
    The value is passed as parameter of this instruction.
    .P
    If the prefix is defined, it is added directly within the value of the useless type.
    .P
    This instruction raises no interruption.
    %}

Générez à nouveau l'extension et rouvrez la page de manuel. Les objets de l'extension sont enfin documentés.

Chaque objet peut recevoir une section `help` suivie d'une chaine entre double-quote lorsque l'aide tient sur une ligne ou d'un bloc si plusieurs lignes sont nécessaires. Dans les deux cas, le contenu de l'aide est en groff.

Notez que les dépendances aussi peuvent être documentées en ajoutant une section `help` après chaque objet dont dépend l'extension, potentiellement pour indiquer pourquoi cette dépendance existe.

- A chaque dépendance et chaque objet défini par une extension peut être ajouté une section d'aide `help` suivi d'une chaine entre double-quotes ou d'un bloc.
- Cette aide peut indiquer alors comment utiliser l'objet, ainsi que les cas particuliers à connaître comme les interruptions levées par une instruction.

# Conclusion

Vous venez de voir comment générer l'aide d'une extension.

Le générateur d'extension offre des facilités pour écrire la page de manuel des extensions, en donnant à la fois une vision d'ensemble, une vue précise de chaque objet et des exemples de code.

Souvent, une aide bien construite et exhaustive permet aux utilisateurs d'adopter une extension plus facilement, ce qui peut participer à sa popularité.