Personalización del comportamiento del editor mediante la configuración del lenguaje

Puede implementar la sintaxis personalizada específica del lenguaje en el editor de Visual Studio mediante Configuración de lenguaje para habilitar operaciones de sintaxis específicas del lenguaje. En comparación con el uso de un servidor de lenguaje, el uso de Configuración de lenguaje puede mejorar el rendimiento, ya que todas sus operaciones son locales.

¿Qué es Configuración de lenguaje?

Visual Studio ofrece funcionalidades de edición inteligentes para varios lenguajes de programación a través de extensiones de lenguaje. Configuración de lenguaje complementa los servidores que utilizan el protocolo de servidor de lenguaje (LSP) y proporciona datos declarativos que permiten al editor de Visual Studio tomar decisiones de formato, coloración y finalización sin el retraso que supone realizar una consulta asíncrona al servidor LSP. Las características del lenguaje declarativo se definen en los archivos de configuración. Por ejemplo, las extensiones HTML, CSS y typescript-basic agrupadas con Visual Studio ofrecen un subconjunto de las siguientes características de lenguaje declarativo:

  • Resaltado de sintaxis
  • Finalización del fragmento
  • Coincidencia de corchetes
  • Cierre automático de corchetes
  • Alternancia de comentarios
  • Sangría automática

Visual Studio proporciona la capacidad de las extensiones para definir una configuración de lenguaje para cualquier lenguaje de programación. El archivo de configuración de lenguaje controla las funciones de edición fundamentales, como la alternancia de comentarios y la concordancia y el rodeado de corchetes.

El uso de Configuración de lenguaje ayuda con:

  • Trabajo sincrónico de la escritura del usuario
  • Simplicidad: los archivos JSON cortos con expresiones regulares son más fáciles de mantener que el algoritmo complejo.
  • Portabilidad: no requiere cambios, o estos son mínimos, entre Visual Studio Code y Visual Studio.

Además, los archivos de configuración de lenguaje proporcionan una forma sencilla de ampliar Visual Studio para que admita algunas funciones básicas de refactorización a través de un archivo JSON fácil de leer.

Adición de compatibilidad con configuración de lenguaje a una extensión de Visual Studio

Hay tres partes para añadir compatibilidad de configuración de lenguaje a una extensión de Visual Studio:

  1. Crear un proyecto de VSIX
  2. Crear un archivo de configuración de lenguaje
  3. Agregar un archivo de gramática
  4. Actualizar el archivo pkgdef

Puede explorar un ejemplo de trabajo en Ejemplo de configuración de lenguaje.

Crear un proyecto de VSIX

Para crear una extensión de servicio de lenguaje con Configuración de lenguaje, primero asegúrese de que tiene instalada la carga de trabajo de desarrollo de extensiones de Visual Studio para la instancia de VS.

A continuación, cree un nuevo proyecto de VSIX; para ello, vaya a Archivo>Nuevo proyecto, busque "vsix" y busque Proyecto de VSIX:

Screenshot showing how to create a VSIX project.

Crear un archivo de configuración de lenguaje

Al crear su propio archivo de configuración de lenguaje, puede elegir qué aspectos incorporar en el archivo JSON. Por ejemplo, puede optar por admitir la alternancia de comentarios, el cierre automático de llaves o cualquier combinación de la funcionalidad disponible que se describe en esta sección.

Para agregar compatibilidad con la extensión, primero debe crear un archivo de configuración de lenguaje. El nombre del archivo debe seguir un estándar: use guiones para separar las palabras del nombre de archivo y asegúrese de que termina con language-configuration.json.

El código siguiente muestra un archivo de configuración de lenguaje de ejemplo.

{
    "comments": {
      "lineComment": "***",
      "blockComment": ["{*", "*}"]
    },
    "brackets": [
      ["@", "@"],
      ["#", "#"],
      ["$", "$"],
      ["(", ")"]
    ],
    "autoClosingPairs": [
      { "open": "{", "close": "}" },
      { "open": "@", "close": "@" },
      { "open": "#", "close": "#" },
      { "open": "$", "close": "$" },
      { "open": "(", "close": ")" },
      { "open": "'", "close": "'", "notIn": ["string", "comment"] },
      { "open": "\"", "close": "\"", "notIn": ["string"] },
    ],
    "autoCloseBefore": ";:.,=}])>` \n\t",
    "surroundingPairs": [
      ["@", "@"],
      ["#", "#"],
      ["$", "$"],
      ["[", "]"],
      ["(", ")"],
      ["'", "'"],
      ["\"", "\""],
      ["`", "`"]
    ],
    "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
    "indentationRules": {
      "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
      "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
    }
  }

Parámetros de configuración

En las secciones siguientes se describen las opciones disponibles en el archivo de configuración de lenguaje.

Alternancia de comentarios

Los archivos de configuración de lenguaje ofrecen dos comandos para alternar comentarios. Alternar comentario de línea y Alternar comentario de bloque. Puede especificar comments.blockComment y comments.lineComment para controlar cómo Visual Studio debe comentar líneas o bloques.

{
  "comments": {
    "lineComment": "//",
    "blockComment": ["/*", "*/"]
  }
}

Esta configuración afecta al comportamiento del editor de texto de Visual Studio al pulsar Ctrl+K, Ctrl+C.

Definición de corchetes

Al mover el cursor a un corchete definido aquí, Visual Studio resalta ese corchete junto con su par coincidente.

{
  "brackets": [["{", "}"], ["[", "]"], ["(", ")"]]
}

La configuración pertinente en el cuadro de diálogo Herramientas > Opciones de Visual Studio, en Editor de texto, General, Mostrar, es la casilla Habilitar coloración del par de llaves.

Cierre automático

Al escribir ', Visual Studio crea un par de comillas simples y coloca el cursor en el centro: '|'. En esta sección se definen estos pares.

{
  "autoClosingPairs": [
    { "open": "{", "close": "}" },
    { "open": "[", "close": "]" },
    { "open": "(", "close": ")" },
    { "open": "'", "close": "'", "notIn": ["string", "comment"] },
    { "open": "\"", "close": "\"", "notIn": ["string"] },
    { "open": "`", "close": "`", "notIn": ["string", "comment"] },
    { "open": "/**", "close": " */", "notIn": ["string"] }
  ]
}

La llave notIn deshabilita esta característica en determinados intervalos de código. Por ejemplo, al escribir el siguiente código:

// ES6's Template String
`ES6's Template String`;

La comilla simple no se cierra automáticamente.

Los pares que no requieren una propiedad notIn también pueden usar una sintaxis más sencilla:

{
  "autoClosingPairs": [ ["{", "}"], ["[", "]"] ]
}
Cierre automático antes

De forma predeterminada, Visual Studio solo cierra automáticamente pares si hay un espacio en blanco justo después del cursor. Por lo tanto, al escribir { en el código JSX siguiente, no se realizará el cierre automático:

const Component = () =>
  <div className={>
                  ^ Does not get autoclosed by default
  </div>

Sin embargo, esta definición anula ese comportamiento:

{
  "autoCloseBefore": ";:.,=}])>` \n\t"
}

Ahora, al escribir { justo antes de >, Visual Studio aplica el cierre automático con }.

Rodeado automático

Al seleccionar un intervalo en Visual Studio y escribir un corchete de apertura, Visual Studio rodea el contenido seleccionado con un par de corchetes. Esta característica se denomina rodeado automático y aquí puede definir los pares de rodeado automático para un lenguaje específico:

{
  "surroundingPairs": [
    ["{", "}"],
    ["[", "]"],
    ["(", ")"],
    ["'", "'"],
    ["\"", "\""],
    ["`", "`"]
  ]
}

La configuración pertinente en Herramientas > Opciones de Visual Studio está en Editor de texto, General, Mostrar la casilla Rodear automáticamente las selecciones al escribir comillas o corchetes.

Patrón de palabra

wordPattern define lo que se considera una palabra en el lenguaje de programación. Las características de sugerencia de código usan esta configuración para determinar los límites de palabras si se ha establecido wordPattern.

{
  "wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\-\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)"
}

Reglas de sangría

indentationRules define cómo debe ajustar el editor la sangría de la línea actual o de la siguiente al escribir, pegar y mover líneas, o al aplicar formato al texto con Ctrl+K, Ctrl+D (Formato de documento) y Ctrl+K, Ctrl+F (Formato de selección).

{
  "indentationRules": {
    "increaseIndentPattern": "^((?!\\/\\/).)*(\\{[^}\"'`]*|\\([^)\"'`]*|\\[[^\\]\"'`]*)$",
    "decreaseIndentPattern": "^((?!.*?\\/\\*).*\\*/)?\\s*[\\)\\}\\]].*$"
  }
}

Por ejemplo, si if (true) { coincide con increaseIndentPattern, si pulsa Entrar después del corchete de apertura {, el editor sangrará automáticamente una vez y el código terminará como:

if (true) {
  console.log();

Además de increaseIndentPattern y decreaseIndentPatter, hay otras dos reglas de sangría:

  • indentNextLinePattern - Si una línea coincide con este patrón, se debe aplicar sangría una vez solo a la siguiente línea.
  • unIndentedLinePattern - Si una línea coincide con este patrón, no se debe cambiar la sangría y no se debe evaluar con las demás reglas.

Si no hay ninguna regla de sangría establecida para el lenguaje de programación, el editor aplicará la sangría cuando la línea termine con un corchete de apertura y quitará la sangría cuando escriba un corchete de cierre. El corchete aquí se define mediante brackets.

Pulsar Entrar

onEnterRules define una lista de reglas que se van a evaluar cuando se pulse Entrar en el editor.

{
  "onEnterRules": [{
    "beforeText": "^\\s*(?:def|class|for|if|elif|else|while|try|with|finally|except|async).*?:\\s*$",
    "action": { "indent": "indent" }
  }]
}

Al pulsar Entrar, el texto anterior, posterior o una línea por encima del cursor se comprueba con las siguientes propiedades:

  • beforeText (obligatorio). Expresión regular que coincide con el texto antes del cursor (limitado a la línea actual).
  • afterText. Expresión regular que coincide con el texto después del cursor (limitado a la línea actual).
  • previousLineText. Expresión regular que coincide con el texto de una línea por encima del cursor.

Si todas las propiedades especificadas coinciden, se considera que la regla coincide y no se evalúan más reglas onEnterRules. onEnterRule puede especificar las siguientes acciones:

  • indent (obligatorio). Una de las siguientes: none, indent, outdent, indentOutdent.
    • none significa que la nueva línea hereda la sangría de la línea actual.
    • indent significa que a la nueva línea se aplica una sangría en relación con la línea actual.
    • outdent significa que se quita la sangría de la nueva línea en relación con la línea actual.
    • indentOutdent significa que se insertan dos nuevas líneas, una con sangría y la segunda sin sangría.
  • appendText. Cadena que se anexa después de la nueva línea y después de la sangría.
  • removeText. Número de caracteres que se van a quitar de la sangría de la nueva línea.

Configuración de propiedades

En el proyecto de extensión, asegúrese de que el archivo language-configuration.json tenga la siguiente configuración de propiedad:

Build Action = Content
Include in VSIX = True
Copy to output = Copy always 

(opcional) Agregar un archivo de gramática

También puede agregar un archivo de gramática TextMate para proporcionar colores de sintaxis para el idioma. Las gramáticas TextMate son una colección estructurada de expresiones regulares que se escriben como archivos plist (XML) o JSON. Consulte Gramáticas del lenguaje. Si no proporciona un archivo de gramática específico de lenguaje, se usa una configuración predeterminada integrada.

Para agregar archivos personalizados de gramática o tema de TextMate, siga estos pasos:

  1. Cree una carpeta denominada "Gramáticas" dentro de la extensión (o puede ser el nombre que elija).

  2. Dentro de la carpeta Gramáticas, incluya cualquier archivo *.tmlanguage, *.plist, *.tmtheme o *.json que desee que proporcione coloración personalizada.

    Sugerencia

    Un archivo .tmtheme define cómo se asignan los ámbitos a las clasificaciones de Visual Studio (claves de color con nombre). A modo de orientación, puede consultar el archivo .tmtheme en el directorio %ProgramFiles(x86)%\Microsoft Visual Studio\<version>\<SKU>\Common7\IDE\CommonExtensions\Microsoft\TextMate\Starterkit\Themesg.

Crear un archivo pkgdef

A continuación, cree un archivo .pkgdef. Un archivo .pkgdef contiene toda la información de registro que, de lo contrario, se agregaría al registro del sistema. Para obtener más información sobre los archivos pkgdef, consulte Registro de VSPackages y ¿Qué es un archivo pkgdef? ¿Y para qué sirve?. En el archivo pkgdef, debe tener la ruta de acceso al archivo language-configuration.json y la ruta de acceso de la gramática del lenguaje. Los servicios de lenguaje como LSP solicitan el tipo de contenido del editor y lo obtienen a través de Configuración de lenguaje. Esta información proporciona la inteligencia específica del lenguaje dentro de un servidor que puede comunicarse con herramientas de desarrollo. Cuando no existe un servicio de lenguaje, el motor de Configuración de lenguaje vuelve a la gramática TextMate. El archivo .pkgdef debería tener este aspecto:

[$RootKey$\TextMate\Repositories]
"AspNetCoreRazor="$PackageFolder$\Grammars

// Defines where the language configuration file for a given
// grammar name is (value of the ScopeName tag in the tmlanguage file).
[$RootKey$\TextMate\LanguageConfiguration\GrammarMapping]
"text.aspnetcorerazor"="$PackageFolder$\language-configuration.json"

// Defines where the language configuration file for a given
// language name is (partial value of the content type name).
[$RootKey$\TextMate\LanguageConfiguration\ContentTypeMapping]
"RazorLSP"="$PackageFolder$\language-configuration.json"

[$RootKey$\TextMate\LanguageConfiguration\GrammarMapping]
"text.html.basic"="$PackageFolder$\html-language-configuration.json"
"source.js"="$PackageFolder$\javascript-language-configuration.json"
"source.css"="$PackageFolder$\css-language-configuration.json"
"source.cs"="$PackageFolder$\csharp-language-configuration.json

Asegúrese de que las propiedades del archivo pkgdef estén establecidas de la siguiente manera:

Build Action = Content
Include in VSIX = True
Copy to output = Copy always 

Para que Visual Studio pueda acceder a la información de configuración del lenguaje, incluya el archivo language-configuration en el paquete de VSIX. Incluir este archivo significa que se enviarán con la extensión de Visual Studio. El archivo permite a Visual Studio saber que hay disponible una configuración de lenguaje para su uso. Para agregar el archivo, edite vsixmanifest para agregar el archivo de definición PKGDEF, por ejemplo:

<Asset Type="Microsoft.VisualStudio.VsPackage" Path="Test.pkgdef"/>