Outils pour utilisateurs

Outils du site


prog:vsc:module_highlight

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
Prochaine révision
Révision précédente
prog:vsc:module_highlight [2021/02/03 11:39] – Ajout de quelques commentaires dans un fichier JSON rootprog:vsc:module_highlight [2021/02/26 13:22] (Version actuelle) – Ajout de "Utilisation d'un langage existant" root
Ligne 167: Ligne 167:
  
 Chaque ''repository'' contient un dictionnaire de pattern. Chaque ''repository'' contient un dictionnaire de pattern.
 +
 +  * ''match''
  
 Il est possible de ne définir que le pattern avec son type de contenu. Ici, on repère 4 mots clés (''if'', ''while'', ''for'', ''return''). Il est possible de ne définir que le pattern avec son type de contenu. Ici, on repère 4 mots clés (''if'', ''while'', ''for'', ''return'').
Ligne 181: Ligne 183:
 </code> </code>
  
-Dans l'autre exemple ci-dessous, le symbole ''%%"%%'' et ''%%"%%'' désigne le début (''begin'') et la fin (''end'') d'un texte. Ce texte aura comme coloration syntaxique ''string.quoted.double''.+  * ''begin'' et ''end'' 
 + 
 +Dans l'autre exemple ci-dessous, le symbole ''%%"%%'' et ''%%"%%'' désigne le début (''begin'') et la fin (''end'') d'un texte. Là où l'utilisation de ''match'' se limite à une seule ligne, ''begin'' et ''end'' peut être sur une ou plusieurs lignes. Ce texte aura comme coloration syntaxique ''string.quoted.double''
 + 
 +Ensuite, à l'intérieur de ce texte délimité par ''begin'' et ''end'', on cherche tous les ''patterns'' ''\\.'' (tous les caractères d'échappement) et on lui applique la coloration syntaxique ''constant.character.escape''.
  
-Ensuiteà l'intérieur de ce texte, on cherche le pattern ''\\.'' (caractère d'échappement) et on lui applique la coloration syntaxique ''constant.character.escape''. Et on peut faire autant de sous-niveau que nécessaire.+Il y a aussi un double intérêt. Si le caractère d'échappement ''%%\"%%'' apparaitle guillement sera considéré comme un pattern et ne pourra pas être considéré par la contrainte ''end''. Textmate lisant de gauche à droite et le pattern commençant un caratère avant, ''patterns'' sera prioritaire au ''end''Par contre, si ''patterns'' et ''end'' commencent au même caratère, c'est ''end'' qui sera prioritaire.
  
 <code javascript> <code javascript>
Ligne 214: Ligne 220:
  
 Il est aussi possible d'utiliser ''beginCaptures'' et ''endCaptures'' sur les textes correspondant aux expressions régulières de ''begin'' et ''end''. Il est aussi possible d'utiliser ''beginCaptures'' et ''endCaptures'' sur les textes correspondant aux expressions régulières de ''begin'' et ''end''.
 +
 +En plus de ''name'', il existe ''contentName''. Si on applique ''name'' à un pattern, il s'appliquera au texte désigné par ''begin'', ''end'' et le texte au milieu. Par contre, ''contentName'' ne va définir le nom que pour le texte entre les textes désignés par ''begin'' et ''end''. Si les deux sont appliqués, c'est le nom définit par ''contentName'' qui sera prioritaire.
 +
 +Il est aussi possible d'utiliser ''begin'' et ''end'' et de réutiliser leurs contenus dans ''pattern'' via les [[lang:regex#|Positive and Negative Lookahead]].
 +
 +<WRAP center round important 60%>
 +Le pattern de récursion ne fonctionnera plus.
 +</WRAP>
 +
 +
 +<code javascript>
 +"identifiant": {
 +    "begin": "(?=^\\s*(if)\\s)",
 +    "end": "(?<=^\\s*end_if\\s*$)",
 +    "name": "meta.if.definition.cellman.TRAN",
 +    "pattern": [...]
 +},
 +</code>
 +
  
 ====Bonnes pratiques==== ====Bonnes pratiques====
Ligne 265: Ligne 290:
  
   * ''lang.tmLanguage.json''   * ''lang.tmLanguage.json''
 +
 +Le schéma à respecter est [[https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json|tmlanguage.json]].
 +
 +Il est important de comprendre le fichier ''.json'' en exemple, il contient des explications sur comment rédiger les règles en respectant la sémantique et aussi comment gérer les types if/while/... qui sont des blocs d'instructions qui peut être imbriqués.
  
 <file javascript lang.tmLanguage.json> <file javascript lang.tmLanguage.json>
Ligne 318: Ligne 347:
         },         },
         "expression": {         "expression": {
 +            "// Pour faire simple, on dit qu'un expression, c'est soit :": "",
 +            "//   - deux nombres avec un opérateur arithmétique au milieu,": "",
 +            "//   - un nombre.": "",
             "patterns": [             "patterns": [
                 {                 {
Ligne 348: Ligne 380:
         },         },
         "primary_type": {         "primary_type": {
 +            "// On suppose que les types sont des nombres uniquement.": "",
 +            "// Si le type est inconnu, on le déclare invalide.": "",
 +            "// Attention à ne pas déclarer invalide comme fallthrough à chaque pattern.": "",
 +            "// Sinon, les patterns qui include le type s'arrêteront toujours au fallthrough": "",
 +            "// sans lire les étapes suivantes.": "",
             "patterns": [             "patterns": [
                 {                 {
Ligne 360: Ligne 397:
         },         },
         "init_variable": {         "init_variable": {
 +            "// Une initialisation de variable se faire :": "",
 +            "// int variable = expression;": "",
             "patterns": [             "patterns": [
                 {                 {
Ligne 383: Ligne 422:
                         }                         }
                     }                     }
 +                }
 +            ]
 +        },
 +        "if": {
 +            "// Un if a la syntaxe suivante :": "",
 +            "// if expression then": "",
 +            "//   du code.": "",
 +            "// fi": "",
 +            "// La déclaration de la partie code est faite dans l'identifiant code ci-après": "",
 +            "begin": "^(\\s*)(if)(.*)(then)\\s*",
 +            "beginCaptures": {
 +                "2": {
 +                    "name": "keyword.control.lang"
 +                },
 +                "3": {
 +                    "patterns": [
 +                        {
 +                            "include": "#expression"
 +                        }
 +                    ]
 +                },
 +                "4": {
 +                    "name": "keyword.control.lang"
 +                }
 +            },
 +            "// Ici, on utilise le groupe \\1 qui fait référence au groupe 1 de begin": "",
 +            "// Comme il n'est pas possible de détecter les fi correspondant aux if": "",
 +            "// dans le cas de if imbriqués, on utilise l'indentation pour la correspondance.": "",
 +            "end": "^(\\1)(fi)\\s*",
 +            "endCaptures": {
 +                "2": {
 +                    "name": "keyword.control.lang"
 +                }
 +            },
 +            "name": "meta.body.if.definition.lang",
 +            "patterns": [
 +                {
 +                    "include": "#code"
                 }                 }
             ]             ]
         },         },
         "code": {         "code": {
 +            "// Le code représente des instructions entières.": "",
 +            "// Ici, on considère que des nombres et expression peuvent": "",
 +            "// être des instructions mais cela aurait pu être interdit.": "",
             "patterns": [             "patterns": [
                 {                 {
Ligne 419: Ligne 499:
             },             },
             "name": "meta.body.function.definition.lang",             "name": "meta.body.function.definition.lang",
-            "patterns": [ 
-                { 
-                    "include": "#code" 
-                } 
-            ] 
-        }, 
-        "if": { 
-            "begin": "^(\\s*)(if)(.*)(then)\\s*", 
-            "beginCaptures": { 
-                "2": { 
-                    "name": "keyword.control.lang" 
-                }, 
-                "3": { 
-                    "patterns": [ 
-                        { 
-                            "include": "#expression" 
-                        } 
-                    ] 
-                }, 
-                "4": { 
-                    "name": "keyword.control.lang" 
-                } 
-            }, 
-            "end": "^(\\1)(fi)\\s*", 
-            "endCaptures": { 
-                "2": { 
-                    "name": "keyword.control.lang" 
-                } 
-            }, 
-            "name": "meta.body.if.definition.lang", 
             "patterns": [             "patterns": [
                 {                 {
Ligne 485: Ligne 535:
 156 156
 </file>|Version colorée : \\ \\ {{:prog:vsc:module_highlight:hl_example_1.png?200|}}| </file>|Version colorée : \\ \\ {{:prog:vsc:module_highlight:hl_example_1.png?200|}}|
 +
 +====Utilisation d'un langage existant====
 +Une partie du code peut intégrer un langage existant.
 +
 +Il faut définir qu'on va s'injecter dans le ''scopeName'' dans ''package.json''.
 +
 +<code javascript>
 +{
 +  "language": "cellman_stave",
 +  "scopeName": "source.cellman.stave",
 +  "path": "./syntaxes/cellman.tmLanguage.stave.json"
 +},
 +{
 +  "scopeName": "shell.injection",
 +  "path": "./syntaxes/shellscriptInjection.tmGrammar.json",
 +  "injectTo": [
 +    "source.cellman.stave"
 +  ],
 +  "embeddedLanguages": {
 +    "meta.embedded.shellscript": "shellscript"
 +  }
 +}
 +</code>
 +
 +<file javascript shellscriptInjection.tmGrammar.json>
 +{
 +  "scopeName": "shell.injection",
 +  "injectionSelector": "R:meta.embedded.shellscript",
 +  "patterns": [
 +    {
 +      "include": "source.shell"
 +    }
 +  ]
 +}
 +</file>
 +
 +Utilisation du langage importé. Il faut impérativement utiliser ''begin'', ''end'' et ''contentName'' qui sont multiligne.
 +
 +Pour être utiliser en single line, on peut tricher...
 +
 +<code javascript>
 +{
 +  "begin": ".",
 +  "end": "$",
 +  "contentName": "meta.embedded.shellscript"
 +}
 +</code>
 +
 +====Coloration personnalisée====
 +
 +Afin d'avoir une coloration syntaxique sans devoir personnaliser les couleurs, il est impératif que les noms respectent les règles de la [[https://macromates.com/manual/en/language_grammars|syntaxe grammaticale]].
 +
 +A défaut, il faudra définir les couleurs manuellement dans les préférences de l'utilisateur (fichier ''settings.json'') en plus de l'installation de l'extension.
 +
 +Gros inconvénient, cela devra être fait pour chaque thème existant.
 +
 +<code javascript>
 +    "editor.tokenColorCustomizations": {
 +        "[Default Dark+]": {
 +            "textMateRules": [
 +                {
 +                    "scope": [
 +                        "source.cellman.TRAN entity.name.extended.language",
 +                        "Same color than entity.name.function"
 +                    ],
 +                    "settings": {
 +                        "foreground": "#DCDCAA",
 +                    }
 +                }
 +            ]
 +        },
 +    }
 +</code>
 +
 +====Générer le module====
 +
 +===En local===
 +
 +Il faut ajouter le champ ''publisher'' dans ''package.json'' et lancer la commande :
 +
 +<code bash>
 +vsce package
 +</code>
 +
 +Et pour installer le module dans Visual Studio Code :
 +
 +<code bash>
 +code --install-extension myextension.vsix
 +</code>
 +
prog/vsc/module_highlight.1612348765.txt.gz · Dernière modification : 2021/02/03 11:39 de root