29 Mantenimiento de Programas Grandes

Este capítulo describe las características de Emacs para mantener programas y paquetes de tamaño medio y grande. Estas características incluyen:

  • Interfaz unificada para Soporte de Sistemas de Control de Versiones (VCS) que registran el historial de cambios en los archivos fuente.

  • Comandos para manejar proyectos de programación.

  • Un modo especializado para mantener archivos ChangeLog que proporcionan un registro cronológico de los cambios del programa.

  • Xref, un conjunto de comandos para mostrar definiciones de símbolos (también conocidos como «identificadores») y sus referencias.

  • EDE, el IDE propio de Emacs.

  • Un modo para fusionar cambios en las fuentes del programa realizados en ramas de desarrollo separadas.

  • Un modo menor para resaltar referencias a fallos y visitar los informes de fallos referenciados en su rastreador de incidencias.

Si está manteniendo un programa Lisp grande, entonces además de las características descritas aquí, puede encontrar útil la librería Emacs Lisp Regression Testing (ERT) (ver ERT en Emacs Lisp Regression Testing).

29.1 Control de Versiones

Un sistema de control de versiones es un programa que puede registrar múltiples versiones de un archivo fuente, almacenando información como la hora de creación de cada versión, quién la hizo y una descripción de lo que se cambió.

La interfaz de control de versiones de Emacs se llama VC. Los comandos de VC funcionan con varios sistemas de control de versiones diferentes; actualmente, soporta Bazaar, CVS, Git, Mercurial, Monotone, RCS, SRC, SCCS/CSSC, y Subversion. De estos, el proyecto GNU distribuye CVS, RCS y Bazaar.

VC se activa automáticamente cada vez que visita un archivo gobernado por un sistema de control de versiones. Para deshabilitar VC por completo, establezca la variable personalizable vc-handled-backends a nil (vea 29.1.13 Personalización de VC).

Para actualizar la información de estado de VC para el archivo visitado en el búfer actual, usa el comando vc-refresh-state. Este comando es útil cuando ejecuta comandos de control de versiones fuera de Emacs (por ejemplo, desde el prompt de la shell), o si pone el archivo del búfer bajo un sistema de control de versiones diferente, o lo elimina completamente del control de versiones.

VC también se activa automáticamente en los búferes Dired (ver 31 Dired, el Editor de Directorios) que muestran directorios cuyos archivos están controlados por un VCS. Todos los comandos VC descritos en esta sección pueden invocarse desde cualquier búfer Dired que muestre un directorio con archivos controlados por VC; cualquier archivo que esté marcado en un búfer Dired (ver 31.6 Marcas vs. Banderas) se considera que pertenece al conjunto de archivos actual, y los comandos VC operan sobre los archivos de este conjunto de archivos. Esto le permite construir conjuntos de archivos VC que incluyan cualquier archivo que desee, independientemente de su estado VC. (Si no hay archivos marcados cuando se invoca un comando VC desde un búfer Dired, el archivo mostrado en la línea actual del búfer se considera el único archivo del fileset).

29.1.1. Introducción al Control de Versiones

VC le permite usar un sistema de control de versiones desde Emacs, integrando las operaciones de escritura con dicho sistema sin problemas con la edición. Proporciona una interfaz uniforme para operaciones comunes en muchas operaciones de control de versiones.

Algunas operaciones de control de versiones poco comunes o intrincadas, como alterar la configuración del repositorio, no están soportadas en VC. Deberá realizar dichas tareas fuera de VC, por ejemplo, a través de la línea de comandos.

Esta sección proporciona una visión general del control de versiones y describe los sistemas de control de versiones compatibles con VC. Puede saltarse esta sección si ya está familiarizado con el sistema de control de versiones que desea usar.

29.1.1.1 Comprender los Problemas que Aborda

Los sistemas de control de versiones le proporcionan tres capacidades importantes:

  • Reversibilidad: la capacidad de volver a un estado anterior si descubre que alguna modificación que hizo fue un error o una mala idea.

  • Concurrencia: la capacidad de que muchas personas modifiquen la misma colección de archivos sabiendo que las modificaciones conflictivas pueden detectarse y resolverse.

  • Historial: la capacidad de adjuntar datos históricos a sus datos, como comentarios explicativos sobre la intención detrás de cada cambio. Incluso para un programador que trabaja en solitario, los historiales de cambios son una importante ayuda para la memoria; par1.to de varias personas, son una forma de comunicación entre desarrolladores de vital importancia.

29.1.1.2 Sistemas de Control de Versiones Soportados

VC trabaja actualmente con muchos sistemas de control de versiones diferentes, a los que se refiere como back ends:

Nota

back ends hace referencia a la parte del servidor y front-end: a la parte del cliente.

  • Git es un sistema descentralizado de control de versiones creado originalmente por Linus Torvalds para apoyar el desarrollo de Linux (su núcleo). CVS soporta muchas operaciones comunes de Git, pero otras, como la sincronización de repositorios, deben hacerse desde la línea de comandos.

  • CVS es el sistema de control de versiones libre que, hasta alrededor de 2008, usaban la mayoría de los proyectos de software libre. Desde entonces, ha sido sustituido por sistemas más recientes. CVS permite el desarrollo concurrente multiusuario tanto localmente como a través de la red. A diferencia de los sistemas más recientes, carece de soporte para confirmaciones atómicas y movimiento/renombrado de archivos. VC soporta todas las operaciones básicas de edición bajo CVS.

  • Subversion (svn) es un sistema libre de control de versiones diseñado para ser similar a CVS pero sin sus problemas (por ejemplo, soporta commits (confirmaciones) atómicos de conjuntos de ficheros, y versionado de directorios, enlaces simbólicos, metadatos, renombrados, copias y borrados).

  • SCCS fue el primer sistema de control de versiones que se construyó, y hace tiempo que fue sustituido por otros más avanzados. VC compensa ciertas características que faltan en SCCS (por ejemplo, nombres de etiquetas para las versiones) implementándolas por sí mismo. Otras funciones de la CV, como las ramas múltiples, simplemente no están disponibles. Dado que SCCS no es libre, recomendamos evitarlo.

  • CSSC es un sustituto gratuito de SCCS. Debería usar CSSC sólo si, por alguna razón, no puede usar un sistema de control de versiones más reciente y mejor diseñado.

  • RCS es el sistema de control de versiones libre alrededor del cual se construyó inicialmente VC. Es relativamente primitivo: no se puede usar a través de la red, y funciona a nivel de archivos individuales. Casi todo lo que se puede hacer con RCS se puede hacer a través de VC.

  • Mercurial (hg) es un sistema descentralizado de control de versiones muy parecido a Git. VC soporta la mayoría de los comandos de Mercurial, con la excepción de las operaciones de sincronización de repositorios.

  • Bazaar (bzr) es un sistema de control de versiones descentralizado que soporta tanto el versionado basado en repositorios como el descentralizado. VC soporta la mayoría de las operaciones básicas de edición bajo Bazaar.

  • SRC (src) es RCS, recargado-un sistema especializado de control de versiones diseñado para proyectos de un solo archivo trabajados por una sola persona. Permite que múltiples archivos con historiales de control de versiones independientes existan en un directorio, y por lo tanto es particularmente adecuado para el mantenimiento de pequeños documentos, scripts y dotfiles. Aunque usa RCS para el almacenamiento de revisiones, presenta una moderna interfaz de Usuario que ofrece un funcionamiento sin bloqueo y números de versión secuenciales enteros. VC soporta casi todas las operaciones SRC.

29.1.1.3 Conceptos de Control de Versiones

Cuando un archivo está bajo control de versiones, decimos que está registrado (registered) en el sistema de control de versiones. El sistema dispone de un repositorio (repository) que almacena tanto el estado actual del archivo como su historial de cambios, suficiente para reconstruir la versión actual o cualquier versión anterior. El repositorio también contiene otra información, como entradas de registro (log entry) que describen los cambios realizados en cada archivo.

La copia de un archivo controlado por versiones que realmente edita se denomina archivo de trabajo (work file). Puede modificar cada archivo de trabajo como lo haría con un archivo normal. Cuando haya terminado con un conjunto de cambios, puede confirmar (commit o check in) los cambios; esto registra los cambios en el repositorio, junto con una entrada de registro descriptiva.

Un árbol de directorios de archivos de trabajo se denomina árbol de trabajo (work tree).

Cada confirmación crea una nueva revisión en el repositorio. El sistema de control de versiones mantiene un registro de todas las revisiones pasadas y de los cambios que se hicieron en cada revisión. Cada revisión es nombrada por un ID de revisión (revision ID), cuyo formato depende del sistema de control de versiones; en el caso más simple, es sólo un número entero.

Para ir más allá de estos conceptos básicos, necesitará comprender tres aspectos en los que difieren los sistemas de control de versiones. Como se explica en las tres secciones siguientes, pueden estar basados en bloqueos (lock-based) o en fusiones (merge-based); basados en archivos (file-based) o en conjuntos de cambios (changeset-based); y centralizados o descentralizados. VC maneja todos estos modos de funcionamiento, pero no puede ocultar las diferencias.

29.1.1.4. Control de Versiones Basado en Fusiones vs. Basado en Bloqueos

Un sistema de control de versiones normalmente tiene algún mecanismo para coordinar entre Usuarios que quieren cambiar el mismo archivo. Hay dos formas de hacerlo: fusionar y bloquear (merging and locking).

En un sistema de control de versiones que usa la fusión, cada Usuario puede modificar un archivo de trabajo en cualquier momento. El sistema le permite fusionar su archivo de trabajo, que puede contener cambios que no han sido confirmados, con los últimos cambios que otros han confirmado.

Los sistemas de control de versiones más antiguos usan un esquema de bloqueo (locking scheme). En este caso, los archivos de trabajo suelen ser de sólo lectura. Para editar un archivo, pida al sistema de control de versiones que lo haga escribible para Usted bloqueándolo; sólo un Usuario puede bloquear un archivo dado en un momento dado. Este procedimiento es análogo, pero diferente, del bloqueo que usa Emacs para detectar la edición simultánea de archivos ordinarios (ver 19.3.4 Protección contra la Edición Simultánea). Cuando confirma sus cambios, desbloquea el archivo y el archivo de trabajo vuelve a ser de sólo lectura. Otros Usuarios pueden entonces bloquear el archivo para hacer sus propios cambios.

Tanto los sistemas de bloqueo como los de fusión pueden tener problemas cuando varios Usuarios intentan modificar el mismo archivo al mismo tiempo. Los sistemas de bloqueo tienen conflictos de bloqueo (lock conflicts); un Usuario puede intentar sacar un archivo y no poder hacerlo porque está bloqueado. En los sistemas de fusión, los conflictos de fusión (merge conflicts) se producen cuando se confirma un cambio en un archivo que entra en conflicto con un cambio confirmado por otra persona después de su comprobación. Ambos tipos de conflicto deben resolverse mediante el juicio humano y la comunicación. La experiencia ha demostrado que la fusión es superior al bloqueo, tanto por la comodidad para los desarrolladores como por la reducción al mínimo del número y la gravedad de los conflictos que realmente se producen.

SCCS siempre usa bloqueo. RCS está basado en bloqueos por defecto, pero se le puede indicar que opere en un estilo de fusión. CVS y Subversion se basan en la fusión por defecto, pero se les puede indicar que funcionen en modo de bloqueo. Los sistemas descentralizados de control de versiones, como Git y Mercurial, se basan exclusivamente en la fusión (merging-based).

El modo VC soporta tanto el control de versiones por bloqueo como por fusión. Los términos «commit» (confirmar) y «update» (actualizar) se usan en los sistemas de control de versiones más recientes; los sistemas basados en bloqueo más antiguos usan los términos «check in» y «check out». VC oculta las diferencias entre ellos tanto como sea posible.

29.1.1.5 Control de Versiones Basado en Conjuntos de Cambios vs. Basado en Archivos

En SCCS, RCS, CVS y otros primeros sistemas de control de versiones (y también en SRC), las operaciones de control de versiones están basadas en archivos (file-based): cada archivo tiene su propio comentario e historial de revisiones separado del de todos los demás ficheros. Los sistemas más recientes, empezando por Subversion, se basan en conjuntos de cambios (changeset-based): una confirmación puede incluir cambios en varios archivos, y todo el conjunto de cambios se gestiona como una unidad. Cualquier comentario asociado al cambio no pertenece a un único archivo, sino al propio conjunto de cambios.

El control de versiones basado en conjuntos de cambios es más flexible y potente que el control de versiones basado en archivos; normalmente, cuando hay que revertir un cambio en varios archivos, es bueno poder identificarlo y eliminarlo todo fácilmente.

29.1.1.6 Repositorios Descentralizados vs Centralizados

Los primeros sistemas de control de versiones se diseñaron en torno a un modelo centralizado (centralized model) en el que cada proyecto tiene un único repositorio usado por todos los desarrolladores. SCCS, RCS, CVS, Subversion y SRC comparten este tipo de modelo. Uno de sus inconvenientes es que el repositorio es un punto de estrangulamiento para la fiabilidad y la eficiencia.

GNU Arch fue pionero en el concepto de control de versiones distribuido o descentralizado (distributed or decentralized version control), implementado posteriormente en Git, Mercurial y Bazaar. Un proyecto puede tener varios repositorios diferentes, y estos sistemas soportan una especie de super-fusión (super-merge) entre repositorios que intenta reconciliar sus historiales de cambios. En efecto, hay un repositorio para cada desarrollador, y las fusiones de repositorios sustituyen a las operaciones de confirmación.

VC le ayuda a gestionar el tráfico entre sus archivos de trabajo personales y un repositorio. Si el repositorio es un único maestro, o uno de una red de repositorios pares, no es algo de lo que VC tenga que preocuparse.

29.1.1.7 Tipos de Archivo de Registro (archivo log)

Los proyectos que usan un sistema de control de versiones pueden tener dos tipos de registro de cambios. Uno es el registro mantenido por el sistema de control de versiones: cada vez que confirma un cambio, rellena una entrada de registro para el cambio (consulte 29.1.4 Características del Búfer de Entrada de Logs (registros)). Esto se llama registro de control de versiones.

El otro tipo de registro es el archivo ChangeLog (véase 29.3 Registro de Cambios (Change Logs)). Proporciona un registro cronológico de todos los cambios realizados en una gran parte de un programa, normalmente un directorio y sus subdirectorios. Un programa pequeño usaría un archivo ChangeLog; un programa grande puede tener un archivo ChangeLog en cada directorio principal. Véase 29.3 Registro de Cambios (Change Logs). Los programadores han usado registros de cambios desde mucho antes que los sistemas de control de versiones.

Los sistemas de versiones basados en conjuntos de cambios suelen mantener un registro de modificaciones basado en conjuntos de cambios para todo el sistema, lo que hace que los archivos de registro de cambios sean algo redundantes. Una ventaja que conservan es que a veces es útil poder ver el historial de transacciones de un único directorio separado de los de otros directorios. Otra ventaja es que los registros de cambios no pueden fijarse en muchos sistemas de control de versiones.

Un proyecto mantenido con control de versiones puede usar sólo el registro de control de versiones, o puede usar ambos tipos de registros. Puede manejar algunos archivos de una forma y otros de otra. Cada proyecto tiene su política, que se debe seguir.

Cuando la política es usar ambos, normalmente querrá escribir una entrada para cada cambio una sola vez, y luego ponerla en ambos registros. Puede escribir la entrada en ChangeLog, y luego copiarla al búfer de registro con C-c C-a al confirmar el cambio (vea 29.1.4 Características del Búfer de Entrada de Logs (registros)). O puede escribir la entrada en el búfer de registro mientras confirma el cambio (con la ayuda de C-c C-w), y más tarde usar el comando C-x v a para copiarla a ChangeLog (vea 29.1.12.1 Registros de Cambios y CVS).

29.1.2 Control de Versiones y la Línea de Modo

Cuando visita un archivo que está bajo control de versiones, Emacs lo indica en la línea de modo. Por ejemplo, Bzr-1223 dice que se usa Bazaar para ese archivo, y el ID de revisión actual es 1223.

El carácter entre el nombre del back-end (el nombre del programa del lado servidor o motor) y el ID de revisión indica el estado del control de versiones del archivo de trabajo. En un sistema de control de versiones basado en fusión, un carácter - indica que el archivo de trabajo no ha sido modificado, y : indica que ha sido modificado. El carácter ! indica que el archivo contiene conflictos como resultado de una operación de fusión reciente (véase 29.1.11.3 Fusión de Ramas Fusión de Ramas), o que el archivo ha sido eliminado del control de versiones. Por último, ? significa que el archivo está bajo el control de versiones, pero no está en el árbol de trabajo.

En un sistema basado en bloqueos, - indica un archivo desbloqueado, y : un archivo bloqueado; si el archivo está bloqueado por otro Usuario (por ejemplo, jim), se muestra como RCS:jim:1.3. @ significa que el archivo ha sido añadido localmente, pero aún no ha sido enviado al repositorio maestro.

En una pantalla gráfica, puede mover el ratón sobre este indicador de línea de modo para que aparezca una caja de herramientas (tool-tip), que muestra una descripción más detallada del estado del control de versiones. Pulsando con ratón-1 sobre el indicador aparece un menú de comandos VC, idéntico al de Tools / Version Control (Herramientas / Control de versiones) de la barra de menús.

Cuando el modo Auto Revert (ver 19.4 Revertir un Búfer) revierte un búfer que está bajo control de versiones, actualiza la información de control de versiones en la línea de modo. Sin embargo, el modo Auto Revert puede no actualizar correctamente esta información si el estado del control de versiones cambia sin cambios en el archivo de trabajo, desde fuera de la sesión actual de Emacs. Si establece auto-revert-check-vc-info a t, el modo Auto Revert actualiza la información del estado del control de versiones cada auto-revert-interval segundos, incluso si el propio archivo de trabajo no ha cambiado. El uso de CPU resultante depende del sistema de control de versiones, pero normalmente no es excesivo.

29.1.3 Edición Básica bajo Control de Versiones (VC)

La mayoría de los comandos VC operan sobre conjuntos de ficheros VC (filesets VC). Un conjunto de archivos VC es una colección de uno o más archivos sobre los que actúa una operación VC. Cuando se escriben comandos VC en un búfer que visita un archivo controlado por versiones, el conjunto de archivos de este Control de Versiones (VC) es simplemente ese archivo. Cuando los escribe en un búfer de directorio VC y algunos de los archivos que contiene están marcados, el conjunto de archivos VC está formado por los archivos marcados (véase 29.1.10 Modo Directorio VC). Del mismo modo, cuando invoca un comando VC desde un búfer Dired, el conjunto de archivos VC está formado por los archivos marcados (vea 31.6 Marcas vs. Banderas), por defecto el archivo mostrado en la línea actual si no hay archivos marcados.

En los sistemas modernos de control de versiones basados en conjuntos de cambios (ver 29.1.1.5 Control de Versiones Basado en Conjuntos de Cambios vs. Basado en Archivos), los comandos VC manejan los conjuntos de archivos VC multi-fichero como un grupo. Por ejemplo, confirmar un conjunto de archivos CV de varios ficheros genera una única revisión, que contiene los cambios de todos esos archivos. En antiguos sistemas de control de versiones basados en archivos como CVS, cada archivo de un conjunto de archivos CV multi-fichero se maneja individualmente; por ejemplo, una confirmación genera una revisión para cada archivo cambiado.

Ctrl-x vv (C-x v v)

Realiza la siguiente operación de control de versiones apropiada en el conjunto de archivos VC actual.

El comando principal de VC es un comando multipropósito, C-x v v (vc-next-action), que realiza la acción más apropiada en el conjunto de archivos VC actual: registrarlo en un sistema de control de versiones, confirmarlo (commiting), desbloquearlo (unblocking) o fusionarlo (merging) cambios en él. Las acciones concretas se describen con detalle en las subsecciones siguientes. Puede usar C-x v v tanto en un búfer de visita de archivos, en un búfer Dired, o en un búfer de directorio VC; en los dos últimos casos el comando opera sobre el conjunto de archivos formado por los archivos marcados.

Tenga en cuenta que los conjuntos de archivos VC son distintos de los conjuntos de archivos con nombre que se usan para ver y visitar archivos en grupos funcionales (véase 19.20 Conjunto de Archivos). A diferencia de los conjuntos de archivos con nombre, los conjuntos de archivos VC no tienen nombre y no persisten entre sesiones.

29.1.3.1 Control de Versiones Básico con Fusión

En un sistema de control de versiones basado en fusión (es decir, la mayoría de los modernos; véase 29.1.1.4. Control de Versiones Basado en Fusiones vs. Basado en Bloqueos), C-x v v hace lo siguiente:

  • Si hay más de un archivo en el conjunto de archivos VC y los archivos tienen estados de control de versiones inconsistentes, señalará un error. (Tenga en cuenta, no obstante, que un conjunto de archivos puede incluir tanto archivos recién añadidos como archivos modificados; consulte 29.1.5 Registro de un Archivo para el Control de Versiones).

  • Si ninguno de los archivos del conjunto de archivos VC está registrado en un sistema de control de versiones, registre el conjunto de archivos VC, es decir, póngalo bajo control de versiones. Véase 29.1.5 Registro de un Archivo para el Control de Versiones. Si Emacs no puede encontrar un sistema bajo el que registrarse, pregunta por un tipo de repositorio, crea un nuevo repositorio y registra el conjunto de ficheros VC en él.

  • Si todos los archivos de trabajo del conjunto de archivos VC no se han modificado, no haga nada.

  • Si cada archivo de trabajo en el conjunto de archivos VC ha sido modificado, confirma los cambios. Para hacer esto, Emacs abre un búfer vc-log; escriba la entrada de registro deseada para la nueva revisión, seguida de C-c C-c para confirmar. Vea 29.1.4 Características del Búfer de Entrada de Logs (registros).

    Si confirma en un repositorio compartido, la confirmación puede fallar si el repositorio ha cambiado desde su última actualización. En ese caso, debe realizar una actualización antes de intentarlo de nuevo. En un sistema de control de versiones descentralizado, use C-x v + (vea 29.1.11.2. Enviar/Recibir Cambios a/desde una Rama) o C-x v m (vea 29.1.11.3 Fusión de Ramas). En un sistema de control de versiones centralizado, teclee Ctrl-x vv (C-x v v) de nuevo para fusionar los cambios del repositorio.

  • Finalmente, si está usando un sistema de control de versiones centralizado, compruebe si cada archivo de trabajo en el conjunto de archivos VC está actualizado. Si algún archivo ha cambiado en el repositorio, ofrézcase a actualizarlo.

Estas reglas también se aplican cuando usa RCS en su modo sin bloqueo, excepto que los cambios no se fusionan automáticamente desde el repositorio. Nada le informa si otro Usuario ha confirmado cambios en el mismo archivo desde que Usted empezó a editarlo; cuando Usted confirma su revisión, los cambios de ese otro Usuario son eliminados (sin embargo, permanecen en el repositorio y por tanto no se pierden irrevocablemente). De modo que, debe verificar que la revisión actual no ha cambiado antes de confirmar sus cambios. Además, el bloqueo es posible con RCS incluso en este modo: C-x v v con un archivo sin modificar bloquea el archivo, tal como lo hace con RCS en su modo de bloqueo normal (vea 29.1.3.2. Control de Versiones Básico con Bloqueo).

29.1.3.2. Control de Versiones Básico con Bloqueo

En un sistema de control de versiones basado en bloqueo (como SCCS, y RCS en su modo por defecto), C-x v v hace lo siguiente:

Si hay más de un archivo en el conjunto de archivos VC y los archivos tienen estados de control de versiones inconsistentes, señala un error.

  • Si cada archivo del conjunto de archivos VC no está registrado en un sistema de control de versiones, registre el conjunto de archivos VC. Véase 29.1.5 Registro de un Archivo para el Control de Versiones. Si Emacs no puede encontrar un sistema en el que registrarse, pregunta por un tipo de repositorio, crea un nuevo repositorio y registra el conjunto de ficheros VC en él.

  • Si cada archivo está registrado y desbloqueado, lo bloquea y lo hace escribible, para que pueda empezar a editarlo.

  • Si cada archivo está bloqueado por Ud. y contiene cambios, confirma los cambios. Para hacer esto, Emacs abre un búfer *vc-log*; escriba la entrada de registro deseada para la nueva revisión, seguida de Ctrl-c Ctrl-c (C-c C-c) para confirmar (vea 29.1.4 Características del Búfer de Entrada de Logs (registros)).

  • Si cada archivo está bloqueado por Usted, pero no lo ha cambiado, libere el bloqueo y haga que el archivo sea de sólo lectura de nuevo.

  • Si cada archivo está bloqueado por otro Usuario, pregunte si desea quitar el bloqueo. Si la respuesta es afirmativa, el archivo pasa a estar bloqueado por usted y se envía un mensaje de advertencia al Usuario que lo había bloqueado anteriormente.

Estas reglas también se aplican cuando se usa CVS en modo de bloqueo, excepto que CVS no soporta el robo de bloqueos.

29.1.3.3 Control Avanzado en C-x v v

Cuando se da un argumento prefijo a vc-next-action (C-u C-x v v), sigue realizando la siguiente operación lógica de control de versiones, pero acepta argumentos adicionales para especificar con precisión cómo realizar la operación.

  • Puede especificar el nombre de un sistema de control de versiones. Esto es útil si el conjunto de ficheros puede ser gestionado por más de un sistema de control de versiones, y Emacs no detecta el correcto.

  • En caso contrario, si usa CVS, RCS o SRC, puede especificar un ID de revisión.

    Si el fileset (conjunto de archivos) es modificado (o bloqueado), esto hace que Emacs haga un commit (una confirmación) con ese ID de revisión. Puede crear una nueva rama proporcionando un ID de revisión apropiado (vea 29.1.11. Control de Versiones - Ramas).

    Si el conjunto de ficheros no está modificado (y desbloqueado), esto comprueba la revisión especificada en el árbol de trabajo. También puede especificar una revisión en otra rama proporcionando su ID de revisión o de rama (vea Cambiando entre Ramas). Un argumento vacío (es decir, C-u C-x v v RET) comprueba la última revisión (cabeza) en la rama actual.

    Esto se ignora silenciosamente en un sistema de control de versiones descentralizado. Esos sistemas no le permiten especificar sus propios IDs de revisión, ni usan el concepto de chequeo de archivos individuales.

29.1.4 Características del Búfer de Entrada de Logs (registros)

Cuando le dice a VC que confirme un cambio, aparece un búfer llamado *vc-log*. En este búfer, debe escribir una entrada de registro que describa los cambios que ha realizado (consulte 29.1.1.1 Comprender los Problemas que Aborda). Cuando haya terminado, teclee Ctrl-c Ctrl-c (C-c C-c, log-edit-done) para salir del búfer y confirmar el cambio, junto con su entrada de registro.

El modo principal para el búfer *vc-log* es el modo Log Edit, una variante del modo Text (ver 26.8 Modo Texto). Al entrar en modo Log Edit, Emacs ejecuta los hooks text-mode-hook y vc-log-mode-hook (ver 29.1.4 Características del Búfer de Entrada de Logs (registros)).

En el búfer *vc-log*, puede escribir una o más líneas de cabecera, especificando información adicional que se suministrará al sistema de control de versiones. Cada línea de cabecera debe ocupar una sola línea en la parte superior del búfer; la primera línea que no sea una línea de cabecera se trata como el inicio de la entrada del registro. Por ejemplo, la siguiente línea de cabecera indica que el presente cambio no fue escrito por Usted, sino por otro desarrollador:

Author: J. R. Hacker <jrh@example.com>

Aparte de la cabecera Author (Autor), Emacs reconoce las cabeceras Summary (un resumen de una línea del conjunto de cambios), Date (una hora de confirmación especificada manualmente), y Fixes (una referencia a un error corregido por el cambio). No todos los sistemas de control de versiones reconocen todas las cabeceras. Si especifica una cabecera para un sistema que no la admite, la cabecera se trata como parte de la entrada del registro.

Mientras esté en el búfer *vc-log*, se considera que el conjunto de ficheros VC actual es el que se confirmará si teclea Ctrl-c Ctrl-c (C-c C-c). Para ver una lista de los archivos del conjunto de archivos VC, escriba Ctrl-c Ctrl-f (C-c C-f, log-edit-show-files). Para ver una diferencia de cambios entre el conjunto de archivos VC y la versión desde la que empezó a editar (vea 29.1.6 Revisión y Comparación de Versiones Anteriores), teclee Ctrl-c Ctrl-d (C-c C-d, log-edit-show-diff).

Para ayudar a generar entradas ChangeLog, teclee Ctrl-c Ctrl-w (C-c C-w, log-edit-generate-changelog-from-diff), para generar esqueletos de entradas ChangeLog, listando todos los nombres de archivos y funciones cambiados basados en el diff del conjunto de archivos VC. Las entradas consecutivas que queden vacías se combinarán mediante M-q (fill-paragraph). Por defecto, el esqueleto sólo incluirá el nombre del archivo, sin ningún directorio inicial. Si desea anteponer los directorios iniciales hasta la raíz de VC, personalice diff-add-log-use-relative-names.

Si el conjunto de archivos VC incluye uno o más archivos ChangeLog (ver 29.3 Registro de Cambios (Change Logs)), escriba Ctrl-c Ctrl-Ctrl-a (C-c C-a, log-edit-insert-changelog) para extraer las entradas relevantes en el búfer *vc-log*. Si el elemento superior de cada registro de cambios se hizo bajo su nombre de Usuario en la fecha actual, este comando busca en ese elemento las entradas que coincidan con el/los archivo(s) a confirmar, y las inserta. Si está usando CVS o RCS, vea 29.1.12.1 Registros de Cambios y CVS, para la forma opuesta de trabajar generando entradas de Registro de Cambios desde el búfer de Edición de Registro.

Para abortar una confirmación, simplemente no escriba Ctrl-c Ctrl-c (C-c C-c) en ese búfer. Puede cambiar de búfer y hacer otras ediciones. Mientras no intente hacer otra confirmación, la entrada que estaba editando permanece en el búfer *vc-log*, y puede volver a ese búfer en cualquier momento para completar la confirmación.

También puede navegar por el historial de entradas de registro anteriores para duplicar un comentario de confirmación. Esto puede ser útil cuando quiera hacer varias confirmaciones con comentarios similares. Los comandos M-n, M-p, M-s y M-r para hacer esto funcionan igual que los comandos de historial del minibúfer (ver 9.5 Historial del Minibúfer), excepto que se usan fuera de éste.

29.1.5 Registro de un Archivo para el Control de Versiones

Ctrl-x vi (C-x v i)

Registra el archivo visitado para el control de versiones.

El comando C-x v i (vc-register) registra cada archivo en el conjunto de archivos VC actual, poniéndolo bajo control de versiones. Esto es esencialmente equivalente a la acción de C-x v v en un conjunto de ficheros VC no registrado (ver 29.1.3 Edición Básica bajo Control de Versiones (VC) de Versiones), excepto que si el conjunto de ficheros VC ya está registrado, C-x v i señala un error mientras que C-x v v realiza alguna otra acción.

Para registrar un archivo, Emacs debe elegir un sistema de control de versiones. Para un conjunto de archivos VC de varios ficheros, el búfer Directorio VC especifica el sistema a usar (ver 29.1.10 Modo Directorio VC). Para un conjunto de archivos VC de un solo archivo, si el directorio del archivo ya contiene archivos registrados en un sistema de control de versiones, o si el directorio forma parte de un árbol de directorios controlado por un sistema de control de versiones, Emacs elige ese sistema. En el caso de que más de un sistema de control de versiones sea aplicable, Emacs usa el que aparece primero en la variable vc-handled-backends (ver 29.1.13 Personalización de VC). Si Emacs no puede encontrar un sistema de control de versiones bajo el que registrar el archivo, pregunta por un tipo de repositorio, crea un nuevo repositorio, y registra el archivo en ese repositorio.

En la mayoría de los sistemas de control de versiones, registrar un archivo con C-x v i o C-x v v lo añade al árbol de trabajo pero no al repositorio. Tales archivos se etiquetan como added (añadido) en el búfer del Directorio VC, y muestran un ID de revisión de @@ en la línea de modo. Para que el registro tenga efecto en el repositorio, debe realizar una confirmación (vea 29.1.3 Edición Básica bajo Control de Versiones (VC)). Tenga en cuenta que una única confirmación puede incluir tanto adiciones de archivos como ediciones a archivos existentes.

En un sistema de control de versiones basado en bloqueo (vea 29.1.1.4. Control de Versiones Basado en Fusiones vs. Basado en Bloqueos), registrar un archivo lo deja desbloqueado y de sólo lectura. Escriba Ctrl-x vv (C-x v v) para empezar a editarlo.

29.1.6 Revisión y Comparación de Versiones Anteriores

Ctrl-x v= (C-x v =)

Compara los archivos de trabajo del conjunto de archivos VC actual con las versiones de las que partió (vc-diff). Con un argumento prefijo, pide dos revisiones del conjunto de ficheros VC actual y las compara. También puede invocar este comando desde un búfer de Dired (véase 31 Dired, el Editor de Directorios).

Alt-x vc-ediff (M-x vc-ediff)

Como C-x v =, pero usando Ediff. Véase Ediff en The Ediff Manual.

Ctrl-x vD (C-x v D)

Compara todo el árbol de trabajo con la revisión de la que partió (vc-root-diff). Con un argumento prefijo, pide dos revisiones y compara sus árboles.

Ctrl-x v~ (C-x v ~)

Solicita una revisión del archivo actual, y la visita en un búfer separado (vc-revision-other-window).

Ctrl-x v g (C-x v g)

Muestra una versión anotada del archivo actual: para cada línea, muestra la última revisión en la que se modificó (vc-annotate).

C-x v = (vc-diff) muestra una diferencia (diff) que compara cada archivo de trabajo en el conjunto de archivos VC actual con la(s) versión(es) desde la(s) que comenzó a editar. El diff se muestra en otra ventana, en un búfer del modo Diff (ver 19.10 Modo Diff) llamado *vc-diff*. Los comandos habituales del modo Diferencia están disponibles en este búfer. En particular, el comando g (revert-buffer) realiza la comparación de archivos de nuevo, generando un nuevo diff.

Para comparar dos revisiones arbitrarias del conjunto de archivos VC actual, llame a vc-diff con un argumento de prefijo: C-u C-x v =. Esto solicita dos IDs de revisión (ver 29.1.1.3 Conceptos de Control de Versiones), y muestra una diferencia entre esas versiones del conjunto de ficheros. Esto no funcionará de forma fiable para conjuntos de ficheros VC multi-fichero, si el sistema de control de versiones está basado en ficheros en lugar de en conjuntos de cambios (por ejemplo, CVS), ya que entonces los IDs de revisión para diferentes ficheros no estarían relacionados de forma significativa.

En lugar del ID de revisión, algunos sistemas de control de versiones le permiten especificar revisiones en otros formatos. Por ejemplo, en Bazaar puede introducir date:yesterday como argumento de C-u C-x v = (y comandos relacionados) para especificar la primera revisión confirmada después de ayer. Consulte la documentación del sistema de control de versiones para más detalles.

Si invoca C-x v = o C-u C-x v = desde un búfer de Dired (véase 31 Dired, el Editor de Directorios), el archivo listado en la línea actual se trata como el conjunto de archivos VC actual. El conjunto de archivos VC también puede incluir varios archivos marcados.

M-x vc-ediff funciona como C-x v =, excepto que usa una sesión Ediff. Véase Ediff en The Ediff Manual.

C-x v D (vc-root-diff) es similar a C-x v =, pero muestra los cambios en todo el árbol de trabajo actual (es decir, el árbol de trabajo que contiene el conjunto de archivos VC actual). Si invoca este comando desde un búfer Dired, se aplica al árbol de trabajo que contiene el directorio.

Para comparar dos revisiones arbitrarias de los árboles completos, llame a vc-root-diff con un argumento prefijo: C-u C-x v D. Esto solicita dos IDs de revisión (ver 29.1.13 Personalización de VC), y muestra una diferencia entre esas versiones de los árboles de directorios completos controlados por versiones (RCS, SCCS, CVS, y SRC no soportan esta característica).

Puede personalizar las opciones de diferencias que C-x v = y C-x v D usan para generar diferencias. Las opciones usadas se toman del primer valor no nulo entre las variables vc-backend-diff-switches, vc-diff-switches, y diff-switches (vea 19.9 Comparación de Archivos), en ese orden. Aquí, backend significa el sistema de control de versiones relevante, por ejemplo, bzr para Bazaar. Dado que nil significa comprobar la siguiente variable de la secuencia, cualquiera de las dos primeras puede usar el valor t para significar que no hay ningún cambio. La mayoría de las variables de vc-backend-diff-switches son por defecto nil, pero algunas son por defecto t; estas son para sistemas de control de versiones cuyas implementaciones de diff no aceptan opciones comunes de diff, como Subversion.

Para examinar directamente una versión anterior de un archivo, visite el archivo de trabajo y escriba Ctrl-x v~ revisión RETURN (C-x v ~ revision RET, vc-revision-other-window). Esto recupera la versión del archivo correspondiente a la revisión, la guarda en nombrearchivo.~revisión~, y la visita en una ventana separada.

Muchos sistemas de control de versiones permiten ver archivos anotados con información de revisión por línea, tecleando Ctrl-x vg (C-x v g, vc-annotate). Esto puede crear un nuevo búfer de «anotaciones» mostrando el texto del archivo, con cada línea coloreada para mostrar su antigüedad. El texto rojo es nuevo, el azul es antiguo y los colores intermedios indican edades intermedias. Por defecto, el color se escala sobre todo el rango de edades, de forma que los cambios más antiguos son azules y los más recientes son rojos. Si la variable vc-annotate-background-mode no es nula, los colores que expresan la antigüedad de cada línea se aplican al color de fondo, dejando el primer plano con su color por defecto.

Puede personalizar las opciones de anotación que usa C-x v g personalizando vc-backend-annotate-switches y vc-annotate-switches. Funcionan de forma similar a vc-backend-diff-switches y vc-diff-switches, descritos anteriormente.

Cuando se da un argumento de prefijo a C-x v g, Emacs lee dos argumentos usando el minibúfer: la revisión a mostrar y anotar (en lugar del contenido actual del archivo), y el intervalo de tiempo en días que debe cubrir la gama de colores.

Desde el búfer annotate (anotación), estas y otras opciones de escalado de color están disponibles en el menú VC-Annotate (VC-Anotación). En este búfer, también puede usar las siguientes teclas para navegar por las anotaciones de revisiones pasadas, ver diferencias (diffs), o ver entradas de registro:

p (p)

Anota la revisión anterior, es decir, la revisión anterior a la anotada actualmente. Un argumento de prefijo numérico es un recuento de repeticiones, por lo que C-u 10 p le llevaría 10 revisiones atrás.

n (n)

Anota la siguiente revisión, es decir, la revisión posterior a la anotada actualmente. Un argumento prefijo numérico es un recuento de repeticiones.

j (j)

Anota la revisión indicada por la línea actual.

a (a)

Anota la revisión anterior a la indicada por la línea actual. Esto es útil para ver el estado en que se encontraba el archivo antes de que se realizara el cambio en la línea actual.

f (f)

Muestra en un búfer la revisión del archivo indicada por la línea actual.

d (d)

Muestra la diferencia entre la revisión de la línea actual y la revisión anterior. Esto es útil para ver lo que la revisión de la línea actual realmente cambió en el archivo.

D (D)

Muestra la diferencia entre la revisión de la línea actual y la revisión anterior para todos los archivos en el conjunto de cambios (para sistemas VC que soporten conjuntos de cambios). Esto es útil para ver lo que la revisión de la línea actual ha cambiado realmente en el árbol.

l (l)

Muestra el registro de la revisión de la línea actual. Esto es útil para ver la descripción del autor de los cambios en la revisión de la línea actual.

w (w)

Anota la revisión de trabajo, la que está editando. Si usó p y n para navegar a otras revisiones, use esta tecla para volver a su revisión de trabajo.

v (v)

Cambia la visibilidad de las anotaciones. Esto es útil para ver sólo el contenido del archivo sin distraerse de dichas anotaciones.

29.1.7 Registro de Cambios de CV

Ctrl-x vl (C-x v l)

Muestra el historial de cambios del conjunto de archivos actual (vc-print-log).

Ctrl-x vL (C-x v L)

Muestra el historial de cambios del repositorio actual (vc-print-root-log).

Ctrl-x vbl (C-x v b l)

Muestra el historial de cambios de otra rama (vc-print-branch-log).

Ctrl-x vI (C-x v I)

Muestra los cambios que recuperará una operación «pull» (empujar) (vc-log-incoming).

Ctrl-x vO (C-x v O)

Muestra los cambios que serán enviados por la próxima operación «push» (traer) (vc-log-outgoing).

Ctrl-x vh (C-x v h)

Muestra el historial de cambios realizados en la región de archivo visitada por el búfer actual (vc-region-history).

Atl-x vc-log-search RETURN (M-x vc-log-search RET)

Busca en el historial de cambios un patrón especificado.

C-x v l (vc-print-log) muestra un búfer llamado *vc-change-log*, mostrando el historial de cambios realizados en el conjunto de ficheros actual de forma larga, incluyendo quién hizo los cambios, las fechas y la entrada de registro para cada cambio (estas son las mismas entradas de registro que introduciría a través del búfer *vc-log*; vea 29.1.4 Características del Búfer de Entrada de Logs (registros)). Cuando se invoca desde un búfer que visita un archivo, el conjunto de archivos actual consiste en ese único archivo, y el punto en el búfer *vc-change-log* mostrado se centra en la revisión de ese archivo. Cuando se invoca desde un búfer VC Directory (ver 29.1.10 Modo Directorio VC) o desde un búfer Dired (ver 31 Dired, el Editor de Directorios), el conjunto de ficheros consiste en todos los ficheros marcados, por defecto el fichero mostrado en la línea actual en el búfer del directorio si no hay ningún fichero marcado.

Si el conjunto de archivos incluye uno o más directorios, el búfer *vc-change-log* resultante muestra un registro corto de los cambios (una línea por cada cambio), si el backend de VC lo admite; de lo contrario, muestra el registro en forma larga.

Con un argumento prefijo, el comando pregunta por la revisión a centrar en el búfer *vc-change-log* y por el número máximo de revisiones a mostrar.

C-x v L (vc-print-root-log) muestra un búfer *vc-change-log* que contiene el historial de todo el árbol de directorios controlado por versiones (RCS, SCCS, CVS y SRC no soportan esta función). Con un argumento de prefijo, el comando pregunta por el número máximo de revisiones a mostrar. Un prefijo numérico especifica el número máximo de revisiones sin preguntar. Cuando el argumento prefijo numérico es 1, como en C-1 C-x v L o C-u 1 C-x v L, el comando pregunta por el ID de la revisión, y muestra la entrada de registro de esa revisión junto con los cambios (diffs) que introdujo. (Algunos sistemas de control de versiones menos capaces, como RCS y CVS, no tienen comandos para mostrar un registro de revisión con sus diffs; para ellos el comando sólo muestra la entrada del registro, y puede solicitar que se muestren los diffs tecleando d o D, ver más abajo).

El historial C-x v L se muestra de forma compacta, normalmente mostrando sólo la primera línea de cada entrada de registro. Sin embargo, puede teclear RETURN (RET, log-view-toggle-entry-display) en el búfer *vc-change-log* para mostrar la entrada de registro completa de la revisión en cuestión. Un segundo RETURN (RET) vuelve a ocultarla.

C-x v b l nombre-rama RET (vc-print-branch-log) muestra un búfer *vc-change-log* que muestra la historia del árbol de directorios controlado por versiones, como hace vc-print-root-log, pero muestra la historia de una rama distinta de la actual; pregunta por la rama cuya historia mostrar.

En un sistema de control de versiones descentralizado, el comando C-x v I (vc-log-incoming) muestra un búfer de registro mostrando los cambios que serán aplicados, la próxima vez que ejecute el comando pull del sistema de control de versiones para obtener nuevas revisiones desde otra localización remota (ver 29.1.11.2. Enviar/Recibir Cambios a/desde una Rama). Esta otra localización remota es la localización por defecto desde la que se extraen los cambios, tal y como está definida por el sistema de control de versiones; con un argumento prefijo, vc-log-incoming pregunta por una localización remota específica. De forma similar, C-x v O (vc-log-outgoing) muestra los cambios que se enviarán a otra ubicación remota, la próxima vez que ejecute la orden push; con un argumento prefijo, solicita un destino específico que en el caso de algún sistema de control de versiones puede ser un nombre de rama.

En el búfer vc-change-log, puede usar las siguientes teclas para moverse entre los registros de revisiones y de archivos, y para examinar y comparar revisiones pasadas (vea 29.1.6 Revisión y Comparación de Versiones Anteriores):

p (p)

Se mueve a la entrada de revisión anterior. (Las entradas de revisión en el búfer de registro suelen estar en orden cronológico inverso, por lo que la entrada de revisión anterior suele corresponder a una revisión más reciente). Un argumento prefijo numérico es un recuento de repeticiones.

n (n)

Pasa a la siguiente entrada de revisión. Un argumento prefijo numérico es un recuento de repeticiones.

a (a)

Anotar la revisión en la línea actual (véase 29.1.6).

e (e)

Modifica el comentario de cambios mostrado en el punto. Tenga en cuenta que no todos los sistemas VC permiten modificar este tipo de comentarios.

f (f)

Visita la revisión indicada en la línea actual.

d (d)

Muestra un diff entre la revisión en el punto y la siguiente revisión anterior, para el archivo en cuestión.

D (D)

Muestra la diferencia de cambios entre la revisión en el punto y la siguiente revisión anterior. Esto muestra los cambios en todos los archivos realizados en esa revisión.

RETURN (RET)

En un búfer de registro de estilo compacto (por ejemplo, el creado por C-x v L), alterna entre mostrar y ocultar la entrada de registro completa para la revisión en el punto.

Dado que la obtención de muchas entradas de registro puede ser lenta, el búfer *vc-change-log* no muestra más de 2000 revisiones por defecto. La variable vc-log-show-limit especifica este límite; si se fija el valor a cero, se elimina el límite. También puede aumentar el número de revisiones mostradas en un búfer *vc-change-log* existente pulsando los botones Show 2X entries (Mostrar entradas 2X) o Show unlimited entries (Mostrar entradas ilimitadas) al final del búfer. Sin embargo, RCS, SCCS, CVS y SRC no soportan esta característica.

Una variante útil de examinar el historial de cambios la proporciona el comando vc-region-history (por defecto ligado a C-x v h), que muestra un búfer *VC-history* con el historial de cambios realizados en la región del archivo del búfer actual entre el punto y la marca (ver 12 La marca y la región). El historial de cambios incluye los mensajes de registro de confirmación y también los propios cambios en el formato Diff.

Invoca este comando después de marcar en el búfer actual la región en cuyos cambios estás interesado. En el búfer *VC-history* que aparece, puede usar todos los comandos disponibles en el búfer *vc-change-log* descrito anteriormente, y también los comandos definidos por el modo Diff (ver 19.10 Modo Diff).

Este comando sólo está disponible actualmente con Git y Mercurial (hg).

El comando vc-log-search permite buscar un patrón en el registro de cambios. Solicita un patrón (una expresión regular), y muestra todas las entradas en el historial de cambios cuyos mensajes de registro coincidan con el patrón. Cuando se invoca con un argumento prefijo, el comando también solicitará un comando shell VCS específico para ejecutar con este propósito.

29.1.8 Deshacer Acciones de Control de Versiones

Ctrl-x vu (C-x v u)

Revierte el/los archivo(s) de trabajo en el conjunto de archivos VC actual a la última revisión (vc-revert).

Si desea descartar todos los cambios realizados en el conjunto de archivos VC actual, escriba Ctrl-x vu (C-x v u, vc-revert). Se le pedirá confirmación antes de descartar los cambios. Si está de acuerdo, el conjunto de archivos se revierte.

Si vc-revert-show-diff no es nulo, este comando le mostrará una diferencia entre el archivo(s) de trabajo y la revisión desde la que empezó a editar. Después, el búfer de diferencias será eliminado (si esta variable es kill), o el búfer será enterrado (cualquier otro valor no nulo). Si no quiere que C-x v u muestre una diferencia, establezca esta variable a nil (aún puede ver la diferencia directamente con C-x v =; vea 29.1.6 Revisión y Comparación de Versiones Anteriores).

En sistemas de control de versiones basados en bloqueo, C-x v u deja los archivos desbloqueados; debe bloquearlos de nuevo para reanudar la edición. También puede usar C-x v u para desbloquear un archivo si lo bloquea y luego decide no cambiarlo.

29.1.9 Ignorar Archivos del Control de Versiones

Ctrl-x vG (C-x v G)

Ignora un archivo bajo el sistema de control de versiones actual. (vc-ignorar).

Muchos árboles de fuentes contienen algunos archivos que no necesitan ser versionados, como copias de seguridad del editor, archivos objeto o bytecode, y programas construidos. Puede simplemente no añadirlos, pero entonces siempre aparecerán como archivos desconocidos. También puede decirle al sistema de control de versiones que ignore estos archivos añadiéndolos al archivo de ignorar en la parte superior del árbol. C-x v G (vc-ignore) puede ayudarle a hacer esto. Cuando se llama con un argumento prefijo, puede eliminar un archivo de la lista de archivos ignorados.

29.1.10 Modo Directorio VC

El búfer VC Directory es un búfer especializado para ver los estados de control de versiones de los archivos en un árbol de directorios, y realizar operaciones de control de versiones en esos archivos. En particular, se usa para especificar conjuntos de archivos VC de varios ficheros sobre los que actúan comandos como C-x v v (ver 29.1.10.2. Comandos del Directorio VC Comandos de Directorio VC).

Para usar el búfer del directorio VC, escriba Ctrl-x vd (C-x v d, vc-dir). Esto lee el nombre de un directorio usando el minibúfer, y cambia a un búfer de Directorio VC para ese directorio. Por defecto, el búfer se llama *vc-dir*. Su contenido se describe en El búfer del directorio VC.

El comando vc-dir detecta automáticamente el sistema de control de versiones a usar en el directorio especificado. En el caso de que se esté usando más de un sistema en el directorio, debería invocar el comando con un argumento prefijo, C-u C-x v d; esto pregunta por el sistema de control de versiones que debería usar el búfer VC Directory.

Además del búfer VC Directory, Emacs tiene una herramienta similar llamada PCL-CVS que está especializada en CVS. Ver Acerca de PCL-CVS en PCL-CVS-The Emacs Front-End to CVS.

También puede invocar comandos VC desde los búferes de Dired (vea 31 Dired, el Editor de Directorios). En ese caso, cualquier comando VC que invoque considera los archivos marcados como el conjunto de archivos actual (vea 29.1.3 Edición Básica bajo Control de Versiones (VC)), por defecto el archivo en la línea actual si no hay archivos marcados.

29.1.10.1 Búfer de Directorio VC

El búfer del directorio VC contiene una lista de archivos controlados por versiones y sus estados de control de versiones. Lista los archivos del directorio actual (el especificado al llamar a C-x v d) y sus subdirectorios, pero sólo aquellos con un estado digno de mención. Se omiten los archivos que están actualizados (es decir, los mismos que en el repositorio). Si todos los archivos de un subdirectorio están actualizados, tampoco se enumera el subdirectorio. Como excepción, si un archivo se ha actualizado como resultado directo de un comando VC, se incluye en la lista.

A continuación se muestra un ejemplo de listado del búfer de un directorio VC:

                ./
edited           configure.ac
*   added            README
unregistered     temp.txt
                 src/
*   edited       src/main.c

Traducción:

                ./
editado         configure.ac
* añadido       README
no registrado   temp.txt
                src/
* editado       src/main.c

Dos archivos de trabajo han sido modificados pero no confirmados: configure.ac en el directorio actual, y main.c en el subdirectorio src/. El archivo llamado README ha sido añadido pero aún no está confirmado, mientras que temp.txt no está bajo control de versiones (ver 29.1.5 Registro de un Archivo para el Control de Versiones).

Los caracteres * junto a las entradas de README y src/main.c indican que el Usuario ha marcado estos archivos como el conjunto de archivos VC actual (véase 29.1.10.2. Comandos del Directorio VC).

El ejemplo anterior es típico de un sistema de control de versiones descentralizado como Bazaar, Git o Mercurial. Otros sistemas pueden mostrar otros estados. Por ejemplo, CVS muestra el estado needs-update (necesita-actualización) si el repositorio tiene cambios que no se han aplicado al archivo de trabajo. RCS y SCCS muestran el nombre del Usuario que bloquea un archivo como su estado.

En CVS, el comando vc-dir normalmente contacta con el repositorio, que puede estar en una máquina remota, para comprobar si hay actualizaciones. Si cambia la variable vc-cvs-stay-local a nil (vea 29.1.13.3. Opciones Propias de CVS), entonces Emacs evitará contactar con un repositorio remoto cuando genere el búfer de VC Directory (seguirá contactando con él cuando sea necesario, por ejemplo, cuando haga una confirmación (un commit)). Esto puede ser deseable si está trabajando fuera de lína o la red es lenta.

El búfer de directorios VC omite los subdirectorios listados en la variable vc-directory-exclusion-list. Su valor por defecto contiene directorios que son usados internamente por los sistemas de control de versiones.

29.1.10.2. Comandos del Directorio VC

Emacs proporciona varios comandos para navegar por el búfer del directorio VC, y para marcar archivos como pertenecientes al conjunto de archivos VC actual.

n (n)
SPACE (SPC)

Mueve el punto a la siguiente entrada (vc-dir-next-line).

y (p)

Mueve el punto a la entrada anterior (vc-dir-previous-line).

TAB (TAB)

Pasa a la siguiente entrada de directorio (vc-dir-next-directory).

Shift-TAB (S-TAB)

Se desplaza a la entrada de directorio anterior (vc-dir-previous-directory).

RETURN (RET)
f (f)

Visita el archivo o directorio que aparece en la línea actual (vc-dir-find-file).

o (o)

Visita el archivo o directorio en la línea actual, en una ventana independiente (vc-dir-find-file-other-window).

m (m)

Marca el archivo o directorio en la línea actual (vc-dir-mark), poniéndolo en el conjunto de archivos VC actual. Si la región está activa, marca todos los archivos de la región.

Un archivo no puede marcarse con este comando si ya se encuentra en un directorio marcado o en uno de sus subdirectorios. Del mismo modo, un directorio no puede ser marcado con este comando si cualquier archivo en su árbol está marcado.

M (M)

Si el punto está en una entrada de archivo, marca todos los archivos con el mismo estado; si el punto está en una entrada de directorio, marca todos los archivos de ese árbol de directorios (vc-dir-mark-all-files). Con un argumento prefijo, marca todos los archivos y directorios de la lista.

%m (% m)
*% (* %)

Puede usar este comando para marcar archivos por expreg (vc-dir-mark-by-regexp). Si se le da un prefijo, desmarca los archivos en su lugar.

*r (* r)

Puede usar este comando para marcar archivos que estén en uno de los estados registrados, incluyendo editado, añadido o eliminado. (vc-dir-mark-registered-files).

G (G)

Añade el archivo en cuestión a la lista de archivos que la CV debe ignorar (vc-dir-ignore). Por ejemplo, si la CV es Git, añadirá este archivo al archivo .gitignore. Si se le da un prefijo, hará esto con todos los archivos marcados.

q (q)

Sale del búfer del Directorio VC y lo entierra (quit-window).

u (u)

Desmarca el archivo o directorio de la línea actual. Si la región está activa, desmarca todos los archivos de la región (vc-dir-unmark).

U (U)

Si el punto está en una entrada de archivo, desmarca todos los archivos con el mismo estado; si el punto está en una entrada de directorio, desmarca todos los archivos de ese árbol de directorios (vc-dir-unmark-all-files). Con un prefijo como argumento, se desmarcan todos los archivos y directorios.

x (x)

Oculta archivos con estado “up-to-date” (actualizado) o “ignored” (ignorado) (vc-dir-hide-up-to-date). Con un argumento prefijo, ocultar elementos cuyo estado es el del elemento en el punto.

En el búfer del directorio VC, todos los archivos marcados con m (m, vc-dir-mark) o M (M, vc-dir-mark-all-files) se encuentran en el conjunto de archivos VC actual. Si marca una entrada de directorio con m, todos los archivos listados en ese árbol de directorios están en el conjunto de archivos VC actual. Los archivos y directorios que pertenecen al conjunto de archivos VC actual se indican con un carácter * en el búfer de directorios VC, junto a su estado VC. De este modo, puede configurar un conjunto de archivos VC de varios ficheros para que actúen sobre él comandos VC como C-x v v (consulte 29.1.3 Edición Básica bajo Control de Versiones (VC) ), C-x v = (consulte 29.1.6 Revisión y Comparación de Versiones Anteriores) y C-x v u (consulte 29.1.8 Deshacer Acciones de Control de Versiones).

El búfer del Directorio VC también define algunos atajos de teclado para comandos VC con el prefijo C-x v: =, +, l, i, D, L, G, I, O, y v.

Por ejemplo, puede confirmar un conjunto de archivos editados abriendo un búfer del directorio VC, donde los archivos están listados con el estado edited (editado); marcando los archivos; y tecleando v (v) o Ctrl-x vv (C-x v v, vc-next-action). Si el sistema de control de versiones está basado en conjuntos de cambios, Emacs confirmará los archivos en una única revisión.

Mientras esté en el búfer del directorio VC, también puede realizar búsquedas y reemplazos en el conjunto de ficheros VC actual, con los siguientes comandos:

S (S)

Busca en el conjunto de archivos (vc-dir-search).

Q (Q)

Realiza un reemplazo de consulta de expresión regular en el conjunto de archivos (vc-dir-query-replace-regexp).

Alt-s a Ctrl-s (M-s a C-s)

Realiza una búsqueda incremental en el conjunto de archivos (vc-dir-isearch).

Alt-s a Ctrl-Alt-s (M-s a C-M-s)

Realiza una búsqueda incremental de expresiones regulares en el conjunto de archivos (vc-dir-isearch-regexp).

Aparte de actuar sobre varios archivos, estos comandos se comportan de forma muy similar a sus homólogos de búfer único (véase 16 Búsqueda y Reemplazo).

El búfer del directorio VC define además algunos comandos relacionados con las ramas que empiezan por el prefijo b:

bc (b c)

Crea una nueva rama (vc-create-branch). Consulte 29.1.11.4. Crear Ramas Nuevas.

bl (b l)

Pregunta por el nombre de una rama y muestra el historial de cambios de esa rama (vc-print-branch-log).

bs (b s)

Cambia a una rama (vc-switch-branch). Véase 29.1.11.1 Cambiar entre Ramas.

d (d)

Borra los archivos marcados, o el archivo actual si no hay marcas (vc-dir-clean-delete). Los archivos no se marcarán como borrados en el sistema de control de versiones, por lo que esta función es sobre todo útil para archivos no registrados.

Los comandos anteriores también están disponibles a través de la barra de menús, y a través de un menú contextual invocado por ratón-2. Además, algunos backends de la CV usan el menú para proporcionar comandos adicionales específicos del backend. Por ejemplo, Git y Bazaar te permiten manipular stashes y shelves (que son una forma de apartar temporalmente cambios no comprometidos, y traerlos de vuelta en otro momento).

29.1.11. Control de Versiones - Ramas

Uno de los usos del control de versiones es soportar múltiples líneas independientes de desarrollo, que se denominan ramas. Entre otras cosas, las ramas pueden ser usadas para mantener versiones estables y de desarrollo separadas de un programa, y para desarrollar características no relacionadas aisladas unas de otras.

Actualmente, el soporte de VC para operaciones con ramas es bastante limitado. Para sistemas de control de versiones descentralizados, proporciona comandos para actualizar una rama con el contenido de otra, y para fusionar (merging) los cambios realizados en dos ramas diferentes (véase 29.1.11.3 Fusión de Ramas Fusión de Ramas). Para sistemas de control de versiones centralizados, soporta la comprobación de diferentes ramas y la confirmación en ramas nuevas o diferentes.

29.1.11.1 Cambiar entre Ramas

Los distintos sistemas de control de versiones difieren en cómo se implementan las ramas, y estas diferencias no pueden ser totalmente ocultadas por VC.

En algunos sistemas de control de versiones descentralizados, incluyendo Bazaar y Mercurial en su modo normal de operación, cada rama tiene su propio árbol de directorios de trabajo, por lo que cambiar entre ramas sólo implica cambiar de directorio. En Git, las ramas están normalmente ubicadas en el mismo directorio, y el cambio entre ramas se hace usando el comando git checkout, que cambia el contenido del árbol de trabajo para que coincida con la rama a la que se cambia. Bazaar también soporta ramas co-localizadas, en cuyo caso el comando bzr switch cambiará de rama en el directorio actual. Con Subversion, se cambia a otra rama usando el comando svn switch. Con Mercurial, se usa el comando hg update para cambiar a otra rama.

El comando VC para cambiar a otra rama en el directorio actual es C-x v b s nombre-rama RET (vc-switch-branch).

En sistemas de control de versiones centralizados, también puede cambiar entre ramas tecleando Ctrl-u Ctrl-x vv (C-u C-x v v) en un archivo de trabajo actualizado (vea 29.1.3.3 Control Avanzado en C-x v v Control avanzado en C-x v v), e introduciendo el ID de revisión para una revisión en otra rama. En CVS, por ejemplo, las revisiones en el tronco (la línea principal de desarrollo) normalmente tienen IDs de la forma 1.1, 1.2, 1.3, …, mientras que la primera rama creada a partir de (digamos) la revisión 1.2 tiene IDs de revisión 1.2.1.1, 1.2.1.2, …, la segunda rama creada a partir de la revisión 1.2 tiene IDs de revisión 1.2.2.1, 1.2.2.2, …, y así sucesivamente. También puede especificar el ID de rama, que es un ID de revisión de rama omitiendo su componente final (por ejemplo, 1.2.1), para cambiar a la última revisión de esa rama.

En un sistema basado en bloqueo, cambiar a una rama diferente también desbloquea (write-protects, protección contra escritura) el árbol de trabajo.

Una vez que haya cambiado a una rama, los comandos de VC se aplicarán a esa rama hasta que cambie de rama; por ejemplo, cualquier conjunto de archivos VC que confirme se confirmará en esa rama específica.

29.1.11.2. Enviar/Recibir Cambios a/desde una Rama

Ctrl-x vP (C-x v P)

En un sistema de control de versiones descentralizado, actualiza otra ubicación con los cambios de la rama actual (también conocido como cambios «push»). Este concepto no existe en los sistemas de control de versiones centralizados.

Ctrl-x v+ (C-x v +)

En un sistema de control de versiones descentralizado, actualice la rama actual «extrayendo» (pulling in) los cambios de otra ubicación.

En un sistema de control de versiones centralizado, actualice el conjunto de archivos VC actual.

En un sistema de control de versiones descentralizado, el comando C-x v P (vc-push) actualiza otra ubicación con los cambios de la rama actual. Con un argumento de prefijo, pide el comando exacto de control de versiones a ejecutar, lo que le permite especificar dónde empujar los cambios; por defecto es bzr push con Bazaar, git push con Git, y hg push con Mercurial. Los comandos por defecto siempre empujan a una ubicación predeterminada determinada por el sistema de control de versiones de la configuración de su rama.

Antes de hacer push, puede usar C-x v O (vc-log-outgoing) para ver un búfer de registro de los cambios que se van a enviar. Véase 29.1.7 Registro de Cambios de CV.

Este comando sólo está soportado actualmente por Bazaar, Git y Mercurial. El concepto de «empujar» (pushing) no existe para los sistemas de control de versiones centralizados, donde esta operación es parte de la confirmación de un conjunto de cambios, por lo que invocar este comando en un VCS centralizado señala un error. Este comando también indica un error cuando se intenta en una rama vinculada a Bazaar, donde la confirmación de un conjunto de cambios automáticamente empuja los cambios al repositorio remoto al que está vinculada la rama local.

En un sistema de control de versiones descentralizado, el comando C-x v + (vc-pull) actualiza la rama actual y el árbol de trabajo. Normalmente se usa para actualizar una copia de una rama remota. Si se proporciona un prefijo como argumento, el comando pregunta por el comando exacto de control de versiones a usar, lo que permite especificar de dónde extraer los cambios. De lo contrario, se extraen de una ubicación predeterminada determinada por el sistema de control de versiones.

Entre los sistemas descentralizados de control de versiones, C-x v + sólo está soportado actualmente por Bazaar, Git y Mercurial. Con Bazaar, se llama bzr pull para ramas ordinarias (para tirar de una rama maestra en una rama de reflejo), y bzr update para una rama vinculada (para tirar de un repositorio central). Con Git, llama a git pull para obtener los cambios de un repositorio remoto y fusionarlos en la rama actual. Con Mercurial, llama a hg pull -u para obtener los cambios del repositorio remoto por defecto y actualizar el directorio de trabajo.

Antes de realizar pull, puede usar C-x v I (vc-log-incoming) para ver un búfer de registro de los cambios a aplicar. Véase 29.1.7 Registro de Cambios de CV VC.

En un sistema de control de versiones centralizado como CVS, C-x v + actualiza el conjunto de archivos VC actual desde el repositorio.

29.1.11.3 Fusión de Ramas

Ctrl-:kbd.`x` vm (C-x vm)

En un sistema de control de versiones descentralizado, fusiona los cambios de otra rama en la actual.

En un sistema de control de versiones centralizado, fusiona los cambios de otra rama en el conjunto de archivos de CV actual.

Durante el desarrollo de una rama, a veces puede ser necesario fusionar cambios que ya se han realizado en otra rama. No se trata de una operación trivial, ya que puede haber cambios superpuestos en las dos ramas.

En un sistema de control de versiones descentralizado, la fusión se realiza con el comando C-x v m (vc-merge). En Bazaar, esto pide los argumentos exactos a pasar a bzr merge, ofreciendo un valor por defecto razonable si es posible. En Git, esto pregunta por el nombre de la rama desde la que fusionar, con completado (basado en los nombres de rama conocidos por el repositorio actual). Con Mercurial, esto pregunta por el argumento a pasar a hg merge. El resultado de ejecutar el comando merge se muestra en un búfer separado.

En un sistema de control de versiones centralizado como CVS, C-x v m pide un ID de rama, o un par de IDs de revisión (ver 29.1.11.1 Cambiar entre Ramas); entonces encuentra los cambios de esa rama, o los cambios entre las dos revisiones que especificó, y fusiona esos cambios en el conjunto de ficheros CVS actual. Si sólo teclea RETURN (RET), Emacs simplemente fusiona cualquier cambio que se haya hecho en la misma rama desde que sacaste el archivo.

Inmediatamente después de realizar una fusión, sólo se modifica el árbol de trabajo, y puede revisar los cambios producidos por la fusión con C-x v D y comandos relacionados (vea 29.1.6 Revisión y Comparación de Versiones Anteriores). Si las dos ramas contienen cambios que se solapan, la fusión produce un conflicto; aparece una advertencia en la salida del comando de fusión, y se insertan marcadores de conflicto en cada archivo de trabajo afectado, rodeando los dos conjuntos de cambios en conflicto. A continuación, deberá resolver el conflicto editando los archivos en conflicto. Una vez que haya terminado, los archivos modificados deben confirmarse de la forma habitual para que la fusión surta efecto (consulte 29.1.3 Edición Básica bajo Control de Versiones (VC)).

29.1.11.4. Crear Ramas Nuevas

En sistemas de control de versiones centralizados como CVS, Emacs permite crear nuevas ramas como parte de una operación de confirmación. Al confirmar un conjunto de ficheros CV modificado, escriba (C-u C-x v v, vc-next-action con un argumento de prefijo; véase 29.1.3.3 Control Avanzado en C-x v v). Entonces Emacs le pedirá un ID de revisión para la nueva revisión. Debería especificar un ID de rama adecuado para una rama que comience en la revisión actual. Por ejemplo, si la revisión actual es 2.5, el ID de rama debería ser 2.5.1, 2.5.2, y así sucesivamente, dependiendo del número de ramas existentes en ese punto.

Este procedimiento no funcionará para sistemas de control de versiones distribuidos como git o Mercurial. Para estos sistemas se puede use el comando vc-create-branch (C-x v b c nombre-rama RET).

Para crear una nueva rama en una revisión más antigua (una que ya no es la cabecera de una rama), primero seleccione esa revisión (vea 29.1.11.1 Cambiar entre Ramas). Su procedimiento será diferente dependiendo de si está usando un VCS basado en bloqueo o en fusión.

En un VCS de bloqueo, tendrá que bloquear la rama de la revisión antigua con C-x v v. Se le pedirá que confirme, cuando bloquee la revisión antigua, que realmente quiere crear una nueva rama, si dice que no, se le ofrecerá la oportunidad de bloquear la última revisión en su lugar. En un VCS basado en fusión se saltará este paso.

Luego haga sus cambios y escriba Ctrl-x vv (C-x v v) de nuevo para confirmar una nueva revisión. Esto crea una nueva rama a partir de la revisión seleccionada.

Una vez creada la rama, las confirmaciones posteriores crean nuevas revisiones en esa rama. Para abandonar la rama, debe seleccionar explícitamente una revisión diferente con C-u C-x v v.

29.1.12 Otros Comandos y Funciones de VC

En este apartado se explican las funciones de VC que se usan con menos frecuencia.

29.1.12.1 Registros de Cambios y CVS

Si usa RCS o CVS para un programa con un archivo ChangeLog (vea 29.3 Registro de Cambios (Change Logs)), puede generar entradas de registro de cambios a partir de las entradas de registro de control de versiones de confirmaciones anteriores.

Tenga en cuenta que esto sólo funciona con RCS o CVS. Este procedimiento sería particularmente incorrecto en un sistema de control de versiones moderno basado en conjuntos de cambios, donde los cambios en el archivo ChangeLog (RegistroDeCambios) normalmente se confirmarían como parte de un conjunto de cambios. En ese caso, debería escribir las entradas del registro de cambios primero, y luego arrastrarlas al búfer *vc-log* cuando confirme (vea 29.1.4 Características del Búfer de Entrada de Logs (registros)).

Ctrl-x va (C-x v a)

Visita el archivo ChangeLog del directorio actual y, para los archivos registrados en ese directorio, puede crear nuevas entradas para las versiones confirmadas desde la entrada más reciente del registro de cambios (vc-update-change-log).

Ctrl-u Ctrl-x va (C-u C-x v a)

Como arriba, pero sólo encuentra entradas para el archivo del búfer actual.

Por ejemplo, supongamos que la primera línea de ChangeLog está fechada en 1999-04-10, y que la única entrada desde entonces fue realizada por Nathaniel Bowditch en rcs2log el 1999-05-22 con la entrada Ignore log messages that start with '#'. (Ignorar mensajes de registro que empiecen por “#”). Entonces C-x v a inserta esta entrada ChangeLog:

1999-05-22 Nathaniel Bowditch <nat@apn.org>

    * rcs2log: Ignorar los mensajes de registro que comienzan con '#'.

Si la entrada del registro de control de versiones especifica un nombre de función (entre paréntesis al principio de una línea), eso se refleja en la entrada de ChangeLog. Por ejemplo, si una entrada de registro para vc.el es '(vc-do-command): Comprobar estado de proceso de llamada, la entrada de ChangeLog es:

1999-05-06 Nathaniel Bowditch <nat@apn.org>

    * vc.el (vc-do-command): Comprueba el estado del proceso de llamada.

Cuando C-x v a añade varias entradas de registro de cambios a la vez, agrupa las entradas de registro relacionadas si todas han sido registradas por el mismo autor casi al mismo tiempo. Si las entradas de registro de varios archivos tienen el mismo texto, las agrupa en una única entrada.

29.1.12.2 Borrar y Renombrar Archivos Controlados por Versión

Alt-x vc-delete-file (M-x vc-delete-file)

Solicita un nombre de archivo, elimina el archivo del árbol de trabajo y programa la eliminación para su confirmación.

Alt-x rename-file (M-x vc-rename-file)

Solicita dos nombres de archivo, anterior y nuevo, les cambia el nombre en el árbol de trabajo y programa el cambio de nombre para su confirmación. El archivo anterior toma por defecto el nombre del archivo del búfer actual si está en VC.

Si desea borrar un archivo controlado por versiones, use el comando M-x vc-delete-file. Esto le pedirá el nombre del archivo, y lo borrará a través del sistema de control de versiones. El archivo se elimina del árbol de trabajo, y en el búfer del Directorio VC (ver 29.1.10 Modo Directorio VC), se muestra con el estado removed (eliminado). Cuando lo confirma, la eliminación tiene efecto en el repositorio.

Para renombrar un archivo controlado por versión, escriba Alt-x rename-file (M-x vc-rename-file). Esto le pedirá dos argumentos: el nombre del archivo que desea renombrar, y el nuevo nombre; luego realiza el renombrado a través del sistema de control de versiones. El renombrado tiene efecto inmediato en el árbol de trabajo, y tiene efecto en el repositorio cuando confirma el archivo renombrado.

En los sistemas de control de versiones modernos que tienen soporte integrado para renombrar, el archivo renombrado conserva el historial de cambios completo del archivo original. En CVS y sistemas de control de versiones más antiguos, el comando vc-rename-file funciona creando una copia del fichero antiguo con el nuevo nombre, registrándolo y borrando el fichero antiguo. En este caso, no se conserva el historial de cambios.

29.1.12.3. Etiquetas de Revisión

La mayoría de los sistemas de control de versiones le permiten aplicar una etiqueta de revisión a una versión específica de un árbol controlado por versiones. En los sistemas modernos de control de versiones basados en conjuntos de cambios, una etiqueta de revisión es simplemente un nombre simbólico para una revisión en particular. En sistemas más antiguos basados en ficheros, como CVS, cada etiqueta se añade a todo el conjunto de archivos controlados por versiones, lo que permite manejarlos como una unidad. Las etiquetas de revisión se usan habitualmente para identificar las versiones que se distribuyen a los Usuarios.

Hay dos comandos básicos para las etiquetas; uno crea una etiqueta con un nombre dado, el otro recupera una etiqueta con nombre.

Ctrl-x vs nombre RETURN (C-x v s nombre RET)

Define la revisión de trabajo de cada archivo registrado en o bajo el directorio actual como una etiqueta llamada nombre (vc-create-tag).

Ctrl-x vr nombre RETURN (C-x v r nombre RET)

Para todos los archivos registrados en o por debajo del nivel de directorio actual, recupera el nombre de la revisión etiquetada. Este comando cambiará a una rama si nombre es un nombre de rama y su VCS distingue ramas de etiquetas. (vc-retrieve-tag).

Este comando informa de un error si algún archivo está bloqueado en o por debajo del directorio actual, sin cambiar nada; esto es para evitar sobrescribir el trabajo en curso.

Puede dar una etiqueta o nombre de rama como argumento a C-x v = o C-x v ~ (vea 29.1.6 Revisión y Comparación de Versiones Anteriores). Así, puede usarlo para comparar una versión etiquetada con los archivos actuales, o dos versiones etiquetadas entre sí.

En SCCS, VC implementa etiquetas por sí mismo; estas etiquetas sólo son visibles a través de VC. La mayoría de los sistemas posteriores (incluyendo CVS, Subversion, bzr, git, y hg) tienen una función nativa de etiquetas, y VC la usa cuando está disponible; esas etiquetas serán visibles incluso cuando se salte VC.

En los sistemas de control de versiones basados en ficheros, cuando se renombra un fichero registrado es necesario renombrar su archivo principal junto con él; el comando vc-rename-file lo hará automáticamente (véase 29.1.12.2 Borrar y Renombrar Archivos Controlados por Versión). Si está usando SCCS, también debe actualizar los registros de la etiqueta, para mencionar el archivo por su nuevo nombre (vc-rename-file también lo hace). Una etiqueta antigua que hace referencia a un archivo maestro que ya no existe con el nombre registrado no es válida; VC ya no puede recuperarla. Estaría más allá del alcance de este manual explicar lo suficiente sobre RCS y SCCS como para explicar cómo actualizar las etiquetas a mano. Usar vc-rename-file hace que la etiqueta siga siendo válida para su recuperación, pero no resuelve todos los problemas. Por ejemplo, algunos de los archivos de su programa probablemente hacen referencia a otros por su nombre. Como mínimo, el makefile probablemente menciona el archivo que ha renombrado. Si recupera una etiqueta antigua, el archivo renombrado se recupera con su nuevo nombre, que no es el nombre que espera el makefile. Así que el programa no funcionará realmente como se recuperó.

29.1.12.4. Insertar Cabeceras de Control de Versiones

En Subversion, CVS, RCS y SCCS, puede poner ciertas cadenas especiales llamadas cabeceras de versión en un archivo de trabajo. Cuando se confirma el archivo, el sistema de control de versiones pone automáticamente el número de revisión, el nombre del Usuario que hizo la confirmación, y otra información relevante en la cabecera de versión.

Normalmente, VC no usa la información de las cabeceras de versión. Como excepción, cuando se usa RCS, Emacs usa la cabecera de versión, si la hay, para determinar la versión del archivo, ya que a menudo es más fiable que el archivo maestro de RCS. Para evitar usar la cabecera de versión de esta forma, cambie la variable vc-consult-headers a nil. VC entonces siempre usa los permisos del archivo (si se supone que confía en ellos), o bien comprueba el archivo maestro.

Para insertar una cadena de cabecera adecuada en el búfer actual, use el comandof M-x vc-insert-headers. Este comando sólo funciona en Subversion, CVS, RCS y SCCS. La variable vc-backend-header contiene la lista de palabras clave a insertar en la cabecera de la versión; por ejemplo, CVS usa vc-cvs-header, cuyo valor por defecto es '("\$Id\$"). (Las barras invertidas adicionales evitan que la constante de cadena se interprete como una cabecera, si el archivo Emacs Lisp que la define se mantiene con el control de versiones). El comando vc-insert-headers inserta cada palabra clave de la lista en una nueva línea en el punto, rodeada de tabuladores, y dentro de delimitadores de comentario si es necesario.

La variable vc-static-header-alist especifica más cadenas a añadir en función del nombre del búfer. Su valor debe ser una lista de elementos de la forma (expreg . formato). Siempre que expreg coincida con el nombre del búfer, el formato también se insertará como parte de la cabecera de la versión. Un %s en format se sustituye por el tipo de control de versión del archivo.

29.1.12.5 Edición de Comandos VC

Puede usar el comando prefijo C-x v ! (vc-edit-next-command) para editar la línea de comandos del shell que VC está a punto de ejecutar. Esto está pensado principalmente para hacer posible añadir argumentos de línea de comandos opcionales a los comandos VCS sin complicaciones innecesarias del conjunto de comandos VC y sus interfaces con el servicio de fondo (backend).

Por ejemplo, Git puede producir registros de más de una rama, pero C-x v b l (vc-print-branch-log) solicita el nombre de una sola rama. Para obtener un registro de más de una rama, puede escribir Ctrl-x v! Ctrl-x vbl (C-x v ! C-x v b l) y luego añadir los nombres de las ramas adicionales al final del comando git log que VC está a punto de ejecutar.

29.1.12.6. Preparación de Parches

Cuando se colabora en proyectos es habitual enviar parches por correo electrónico, para compartir cambios. Puede usar para ello el comando vc-prepare-patch de VC. Este comando le preguntará por las revisiones que desea compartir, y qué dirección(es) de correo electrónico de destino usar. Separe las revisiones usando el valor de crm-separator, comas por defecto. El comando preparará esas revisiones usando su MUA (Agente de Usuario de Correo) para que usted las revise y envíe.

Cuando se invoque de forma interactiva en un búfer de Vista de Registro con revisiones marcadas, se usarán esas mismas revisiones marcadas.

Dependiendo del valor de la opción de Usuario vc-prepare-patches-separately, vc-prepare-patch generará uno o más mensajes. El valor por defecto t significa preparar y mostrar un mensaje para cada revisión, uno tras otro. Un valor nil significa generar un único mensaje con todos los parches adjuntos en el cuerpo.

Si espera contribuir con parches de forma regular, puede establecer la opción de Usuario vc-default-patch-addressee a la(s) dirección(es) que desee usar. Esto se usará como valor por defecto al invocar vc-prepare-patch. Los mantenedores de proyectos pueden considerar establecer esto como una variable local de directorio (ver 50.2.5 Variables Locales por Directorio).

29.1.13 Personalización de VC

La variable vc-handled-backends determina qué sistemas de control de versiones debe manejar VC. El valor por defecto es (RCS CVS SVN SCCS SRC Bzr Git Hg), por lo que contiene todos los sistemas de versiones soportados actualmente. Si desea que VC ignore uno o más de estos sistemas, excluya su nombre de la lista. Para deshabilitar VC por completo, establezca esta variable a nil.

El orden de los sistemas en la lista es significativo: cuando visita un archivo registrado en más de un sistema, VC usa por defecto el sistema que aparece primero en vc-handled-backends. El orden también es importante cuando se registra un archivo por primera vez (consulte 29.1.5 Registro de un Archivo para el Control de Versiones).

29.1.13.1. Opciones Generales

Emacs normalmente no guarda archivos de copia de seguridad para archivos fuente que se mantienen con control de versiones. Si desea hacer archivos de copia de seguridad incluso para archivos que usan control de versiones, establezca la variable vc-make-backup-files a un valor no nulo.

La edición de un archivo con control de versiones a través de un enlace simbólico puede provocar resultados inesperados, si desconoce que el archivo subyacente tiene control de versiones. La variable vc-follow-symlinks controla lo que Emacs hace si intenta visitar un enlace simbólico que apunta a un archivo de control de versiones. Si el valor es ask (por defecto), Emacs pide confirmación. Si es nil, Emacs sólo muestra un mensaje de advertencia. Si es t, Emacs sigue automáticamente el enlace y visita el archivo real en su lugar.

Si vc-suppress-confirm es no nil, entonces C-x v v y C-x v i pueden guardar el búfer actual sin preguntar, y C-x v u también funciona sin pedir confirmación.

El modo VC realiza gran parte de su trabajo ejecutando los comandos de shell para el sistema de control de versiones apropiado. Si vc-command-messages no es nulo, VC muestra mensajes para indicar qué comandos shell ejecuta, y mensajes adicionales cuando los comandos finalizan.

29.1.13.2 Opciones para RCS y SCCS

Por defecto, RCS usa el bloqueo para coordinar las actividades de varios Usuarios, pero hay un modo llamado bloqueo no estricto en el que puede registrar cambios sin bloquear el archivo primero. Use rcs -U para cambiar a bloqueo no estricto para un archivo en particular, vea la página del manual de rcs para más detalles.

Cuando se deduce el estado de control de versión de un archivo RCS, VC busca primero una cadena de cabecera de versión RCS en el archivo (ver 29.1.12.4. Insertar Cabeceras de Control de Versiones). Si no hay cadena de cabecera, VC normalmente mira los permisos de archivo del archivo de trabajo; esto es rápido. Pero puede haber situaciones en las que no se pueda confiar en los permisos del archivo. En este caso hay que consultar el archivo maestro, lo que es bastante costoso. Además, el archivo maestro sólo puede decirle si hay algún bloqueo en el archivo, pero no si su archivo de trabajo contiene realmente esa versión bloqueada.

Puede decirle a VC que no use las cabeceras de versión para determinar el estado del archivo poniendo vc-consult-headers a nil. Entonces VC siempre usa los permisos del archivo (si se supone que debe confiar en ellos), o bien comprueba el archivo maestro.

VC determina el estado de control de versiones de los archivos bajo SCCS de forma similar a como lo hace con RCS. Sin embargo, no tiene en cuenta las cabeceras de versión de SCCS. Así, la variable vc-consult-headers no afecta al uso de SCCS.

29.1.13.3. Opciones Propias de CVS

Puede especificar opciones de línea de órdenes adicionales para pasar a todas las operaciones CVS en la variable vc-cvs-global-switches. Estos interruptores se insertan inmediatamente después de la orden cvs, antes del nombre de la operación a invocar.

Cuando se usa un repositorio CVS en una máquina remota, VC puede intentar mantener las interacciones de red al mínimo. Esto se controla mediante la variable vc-cvs-stay-local. Si vc-cvs-stay-local es only-file (por defecto), VC determina el estado del control de versiones de cada archivo usando sólo la entrada en el subdirectorio CVS local y la información devuelta por comandos CVS anteriores. Como consecuencia, si ha modificado un archivo y otra persona ha registrado otros cambios, no se le notificará el conflicto hasta que intente confirmar.

Si cambia vc-cvs-stay-local a nil, VC consulta el repositorio remoto antes de decidir qué hacer en vc-next-action (C-x v v), igual que hace con los repositorios locales.

También puede establecer vc-cvs-stay-local en una expresión regular que se compara con el nombre de host del repositorio; entonces VC permanece local sólo para los repositorios de hosts que coinciden con el patrón.

Cuando se usa un repositorio remoto, Emacs normalmente hace copias de seguridad automáticas de las versiones originales de cada archivo editado. Estas copias de seguridad locales se hacen cada vez que guarda los primeros cambios en un archivo, y se eliminan después de que confirme sus cambios en el repositorio. (Tenga en cuenta que no son lo mismo que los archivos de copia de seguridad ordinarios de Emacs; vea 19.3.2 Archivos de Copia de Seguridad). Comandos como C-x v = y C-x v u usan copias de seguridad automáticas de versiones, si es posible, para evitar tener que acceder a la red.

Establecer vc-cvs-stay-local a nil desactiva la realización de copias de seguridad automáticas.

Las copias de seguridad automáticas de versiones tienen nombres de la forma archivo.~versión.~. Esto es similar al nombre con el que C-x v ~ guarda las versiones antiguas (véase 29.1.6 Revisión y Comparación de Versiones Anteriores), excepto por el punto adicional (.) después de la versión. Los comandos VC relevantes pueden usar ambos tipos de copias de seguridad de versiones. La principal diferencia es que las copias de seguridad manuales realizadas por C-x v ~ no se borran automáticamente al confirmar.

CVS no usa el bloqueo por defecto, pero hay formas de habilitar un comportamiento similar al bloqueo usando su función CVSREAD o watch; consulte la documentación de CVS para más detalles. En ese caso, puede usar C-x v v en Emacs para activar el bloqueo, como lo haría en un sistema de control de versiones basado en bloqueo (vea 29.1.3.2. Control de Versiones Básico con Bloqueo).

29.2 Trabajar con Proyectos

Un proyecto es una colección de archivos usados para producir uno o más programas. Los archivos que pertenecen a un proyecto suelen almacenarse en una jerarquía de directorios; el directorio de nivel superior de la jerarquía se conoce como raíz del proyecto.

El que un directorio dado sea raíz de algún proyecto viene determinado por la infraestructura específica del proyecto, conocida como back-end del proyecto (back-end: es el programa del lado del servidor). Emacs actualmente soporta dos de estos back-ends: VC-aware (véase 29.1 Control de Versiones), por el que un repositorio VCS se considera un proyecto; y EDE (véase 29.5 Entorno de Desarrollo Emacs (EDE)). Se espera que esto se extienda en el futuro para soportar tipos adicionales de proyectos.

El back-end del proyecto también determina qué archivos pertenecen o no a un proyecto. Por ejemplo, el back-end VC-aware no considera que los archivos «ignorados» (véase 29.1.9 Ignorar Archivos del Control de Versiones) formen parte del proyecto. Además, el back-end VC-aware Project considera archivos «no rastreados» (untracked) por defecto. Este comportamiento se puede controlar con la variable project-vc-include-untracked.

29.2.1 Comandos de Proyecto que Operan sobre Archivos

Ctrl-x pf (C-x p f)

Visita un archivo que pertenece al proyecto actual (project-find-file).

Ctrl-x pg (C-x p g)

Busca coincidencias para una expresión regular en todos los archivos que pertenecen al proyecto actual (project-find-regexp).

Alt-x project-search (M-x project-search)

Busca interactivamente coincidencias con expreg en todos los archivos que pertenecen al proyecto actual.

Ctrl-x pr (C-x p r)

Realiza la consulta-reemplazo de una expresión regular (expreg) en todos los archivos que pertenezcan al proyecto actual (project-query-replace-regexp).

Ctrl-x pd (C-x p d)

Ejecuta Dired en el directorio raíz del proyecto actual (project-dired).

Ctrl-x pv (C-x p v)

Ejecuta vc-dir en el directorio raíz del proyecto actual (project-vc-dir).

Ctrl-x ps (C-x p s)

Inicia un shell inferior en el directorio raíz del proyecto actual (project-shell).

Ctrl-x pe (C-x p e)

Inicia Eshell en el directorio raíz del proyecto actual (project-eshell).

Ctrl-x pc (C-x p c)

Ejecuta la compilación en el directorio raíz del proyecto actual (project-compile).

Ctrl-x p! (C-x p !)

Ejecuta el comando shell-command en el directorio raíz del proyecto actual (project-shell-command).

Ctrl-x p& (C-x p &)

Ejecuta el comando shell de forma asíncrona (async-shell-command) en el directorio raíz del proyecto actual (project-async-shell-command).

Emacs proporciona comandos para manejar archivos de proyecto convenientemente. Esta subsección describe estos comandos.

Todos los comandos descritos aquí comparten la noción del proyecto actual. El proyecto actual está determinado por el directorio por defecto (ver 19.1 Nombres de Archivos) del búfer que es el búfer actual cuando se invoca el comando. Si ese directorio no parece pertenecer a un proyecto reconocible, estos comandos le pedirán el directorio del proyecto.

El comando C-x p f (project-find-file, buscar-archivo-de-proyecto) es una forma práctica de visitar archivos (véase 19.2 Visitar Archivos) que pertenecen al proyecto actual. A diferencia de C-x C-f, este comando no requiere escribir el nombre completo del archivo a visitar, puede escribir sólo el nombre base del archivo (es decir, omitir los directorios iniciales). Además, los candidatos a ser completados considerados por el comando incluyen sólo los archivos pertenecientes al proyecto actual, y nada más. Si hay un nombre de archivo en el punto, este comando nofrece ese archivo como primer elemento del «historial futuro». Si se le da un prefijo, incluye todos los archivos bajo la raíz del proyecto, excepto los directorios VCS listados en vc-directory-exclusion-list.

El comando C-x p g (project-find-regexp) es similar a rgrep (véase 28.4 Buscar con Grep en Emacs), pero sólo busca en los archivos que pertenecen al proyecto actual. El comando pregunta por la expresión regular a buscar, y muestra un búfer en modo Xref con los resultados de la búsqueda, donde puede seleccionar una coincidencia usando los comandos del modo Xref (vea 29.4.1.2 Comandos Disponibles en el Búfer *xref*). Cuando se invoca con un argumento de prefijo, este comando solicita además el directorio base desde el que iniciar la búsqueda; esto permite, por ejemplo, limitar la búsqueda sólo a los archivos de proyecto bajo un determinado subdirectorio de la raíz del proyecto. La forma en que este comando muestra las coincidencias se ve afectada por el valor de xref-auto-jump-to-first-xref (véase 29.4.1.3. Buscar y Reemplazar con Identificadores).

M-x project-search es una variante secuencial de project-find-regexp. Solicita una expresión regular para buscar en los archivos del proyecto actual, pero en lugar de encontrar todas las coincidencias y mostrarlas, se detiene cuando encuentra una coincidencia y visita el archivo coincidente en el lugar de la coincidencia, permitiéndole editar el archivo coincidente. Para encontrar el resto de las coincidencias, escriba Alt-x fileloop-continue RETURN (M-x fileloop-continue RET).

C-x p r (project-query-replace-regexp) es similar a project-search, pero le pregunta si desea reemplazar cada coincidencia que encuentra, como hace query-replace (vea 16.10.4 Sustitución de Consultas), y continúa con la siguiente coincidencia después de que Usted responda. Si su respuesta hace que Emacs salga del bucle query-replace, puede continuar más tarde con M-x fileloop-continue RET.

El comando C-x p d (project-find-dir) le pide que elija un directorio dentro del proyecto actual, con finalización. Y abre un búfer Dired (véase 31 Dired, el Editor de Directorios) listando los archivos que contiene.

El comando C-x p D (project-dired) abre un búfer Dired (ver 31 Dired, el Editor de Directorios) listando los archivos en el directorio raíz del proyecto actual.

El comando C-x p v (project-vc-dir) abre un búfer VC Directory (véase 29.1.10 Modo Directorio VC) que lista los estados de control de versiones de los archivos en un árbol de directorios bajo el directorio raíz del proyecto actual.

El comando C-x p s (project-shell) inicia una sesión shell (ver 39 Ejecución de comandos de shell desde Emacs) en un nuevo búfer con la raíz del proyecto actual como directorio de trabajo.

El comando C-x p e (project-eshell) inicia una sesión Eshell en un nuevo búfer con la raíz del proyecto actual como directorio de trabajo. Véase Eshell en Eshell: La Shell de Emacs.

El comando C-x p c (project-compile) ejecuta la compilación (ver 28.1 Ejecutar Compiladores en Emacs) en el directorio raíz del proyecto actual.

El comando C-x p ! (project-shell-command) ejecuta shell-command en el directorio raíz del proyecto actual.

El comando C-x p & (project-async-shell-command) ejecuta async-shell-command en el directorio raíz del proyecto actual.

29.2.2 Comandos de Proyecto que Operan en Búferes

Ctrl-x pb (C-x p b)

Cambia a otro búfer perteneciente al proyecto actual (project-switch-to-buffer).

Ctrl-x p Ctrl-b (C-x p C-b)

Lista los búferes del proyecto (project-list-buffers).

Ctrl-x pk (C-x p k)

Elimina todos los búferes activos que pertenecen al proyecto actual (project-kill-buffers).

Trabajar en un proyecto puede implicar tener muchos búferes visitando archivos que pertenecen al proyecto, y también búferes que pertenecen al proyecto, pero que no visitan ningún archivo (como el búfer de compilación creado por project-compile). El comando C-x p b (project-switch-to-buffer) le ayuda a cambiar entre búferes que pertenecen al proyecto actual solicitando un búfer para cambiar y considerando sólo los búferes del proyecto actual como candidatos a ser completados.

Al igual que el comando listar búferes (véase 20.2 Listado de Búferes Existentes), el comando C-x p C-b (project-list-buffers) muestra una lista de los búferes existentes, pero sólo pertenecientes al proyecto actual.

Cuando termine de trabajar en el proyecto, puede que desee matar todos los búferes que pertenecen al proyecto, para mantener su sesión Emacs más pequeña. El comando C-x p k (project-kill-buffers) lo consigue: elimina todos los búferes que pertenecen al proyecto actual y que satisfacen cualquiera de las condiciones de project-kill-buffer-conditions. Si project-kill-buffers-display-buffer-list no es nulo, los búferes a eliminar se mostrarán primero.

29.2.3 Cambio de Proyectos

Ctrl-x pp (C-x p p)

Ejecuta un comando Emacs para otro proyecto (project-switch-project).

Los comandos que operan sobre archivos de proyecto (vea 29.2.1 Comandos de Proyecto que Operan sobre Archivos Comandos de Proyecto que Operan sobre Archivos) le pedirán convenientemente un directorio de proyecto cuando no haya ningún proyecto en curso. Si se encuentra dentro de un proyecto y desea trabajar con otro, use el comando C-x p p (project-switch-project). Este comando le pide que elija un directorio entre las raíces de proyecto conocidas y, a continuación, muestra el menú de comandos disponibles para operar en el proyecto que elija. La variable project-switch-commands controla qué comandos están disponibles en el menú y qué tecla invoca cada comando.

La variable project-list-file nombra el archivo en el que Emacs registra la lista de proyectos conocidos. Por defecto es el archivo projectos en user-emacs-directory (ver 50.4.4. Cómo encuentra Emacs su Archivo de Inicio).

29.2.4 Gestión del Archivo de Lista de Proyectos

Alt-x project-forget-project (M-x proyecto-olvidar-proyecto)

Elimina un proyecto conocido del archivo de lista de proyectos.

Normalmente Emacs añade y elimina automáticamente proyectos del archivo de lista de proyectos, pero a veces puede querer editar manualmente los proyectos disponibles. M-x project-forget-project le pide que elija uno de los proyectos disponibles, y luego lo elimina del archivo.

29.3 Registro de Cambios (Change Logs)

Muchos proyectos de software mantienen un registro de cambios. Se trata de un archivo, normalmente llamado ChangeLog, que contiene un registro cronológico de cuándo y cómo se ha modificado el programa. A veces, estos archivos se generan automáticamente a partir de las entradas del registro de cambios almacenadas en los sistemas de control de versiones, o se usan para generar estas entradas del registro de cambios. A veces, hay varios archivos de registro de cambios, cada uno registrando los cambios en un directorio o árbol de directorios.

29.3.1. Comandos de Registro de Cambios

El comando C-x 4 a de Emacs añade una nueva entrada al archivo de registro de cambios para el archivo que está editando (add-change-log-entry-other-window). Si ese archivo es en realidad un archivo de copia de seguridad, hace una entrada apropiada para el padre del archivo, es útil para hacer entradas de registro para funciones que han sido borradas en la versión actual.

C-x 4 a visita el archivo de registro de cambios y crea una nueva entrada a menos que la entrada más reciente sea para la fecha de hoy y su nombre. También crea una nueva entrada para el archivo actual. Para muchos idiomas, puede incluso adivinar el nombre de la función u otro objeto que se haya modificado.

Para encontrar el archivo de registro de cambios, Emacs busca en el árbol de directorios desde el archivo que estás editando. Por defecto, se detiene si encuentra un directorio que parece ser la raíz de un repositorio de control de versiones. Para cambiar esto, personalice change-log-directory-files.

Cuando la variable add-log-keep-changes-together es distinta de cero, C-x 4 a añade a cualquier elemento existente para el archivo, en lugar de iniciar un nuevo elemento.

Puede combinar varios cambios de la misma naturaleza. Si no introduce ningún texto después de la C-x 4 a inicial, cualquier C-x 4 a posterior añade otro símbolo a la entrada del registro de cambios.

Si add-log-always-start-new-record no es nulo, C-x 4 a siempre hace una nueva entrada, incluso si la última entrada fue hecha por Usted y en la misma fecha.

Si el valor de la variable change-log-version-info-enabled no es nulo, C-x 4 a añade el número de versión del archivo a la entrada del registro de cambios. Encuentra el número de versión buscando en el primer diez por ciento del archivo, usando expresiones regulares de la variable change-log-version-number-regexp-list.

El archivo de registro de cambios se visita en el modo Registro de Cambios. En este modo principal, cada conjunto de elementos agrupados cuenta como un párrafo, y cada entrada se considera una página. Esto facilita la edición de las entradas. C-j y autocompletar sangría cada nueva línea como la línea anterior; esto es conveniente para introducir el contenido de una entrada.

Puede usar el comando change-log-goto-source (por defecto vinculado a C-c C-c) para ir a la ubicación de origen de la entrada del registro de cambios cerca del punto, cuando el modo Registro de Cambios está activado. Entonces, las invocaciones posteriores del comando 20``next-error`` (por defecto enlazado a M-g M-n y C-x `) se moverán entre las entradas del registro de cambios. Saltará al sitio real del archivo que fue modificado, no sólo a la siguiente entrada del registro de cambios. También puede usar previous-error para retroceder a través de las entradas del registro de cambios.

Puede usar el comando M-x change-log-merge para fusionar otros archivos de registro en un búfer en el modo de registro de cambios, preservando el orden de fechas de las entradas.

Los sistemas de control de versiones son otra forma de hacer un seguimiento de los cambios en su programa y mantener un registro de ellos. Muchos proyectos que usan un VCS no mantienen un archivo de registro de cambios versionado separado hoy en día, así que puede que desee evitar tener tal archivo en el repositorio. Si el valor de add-log-dont-create-changelog-file no es nulo, comandos como C-x 4 a (add-change-log-entry-other-window) registrarán los cambios en un búfer temporal con un nombre apropiado en lugar de en un archivo, si tal archivo no existe ya.

Tanto si tiene un archivo de registro de cambios como si usa un búfer temporal para registros de cambios, puede teclear C-c C-a (log-edit-insert-changelog) en el búfer de registro VC para insertar las entradas de registro de cambios relevantes, si existen. Ver 29.1.4 Características del Búfer de Entrada de Logs (registros).

29.3.2 Formato del Registro de Cambios

Una entrada de registro de cambios comienza con una línea de cabecera que contiene la fecha actual, su nombre (tomado de la variable add-log-full-name), y su dirección de correo electrónico (tomada de la variable add-log-mailing-address). Aparte de estas líneas de cabecera, todas las líneas del registro de cambios comienzan con un espacio o un tabulador. El grueso de la entrada consiste en elementos, cada uno de los cuales comienza con una línea que empieza con un espacio en blanco y una estrella. A continuación se muestran dos entradas, ambas fechadas en mayo de 1993, con dos elementos y un elemento respectivamente.

1993-05-25 Richard Stallman <rms@gnu.org>

    * man.el: Renombra los símbolos 'man-*' a 'Man-*'.
    (manual-entry): Hace más clara la cadena del prompt.

    * simple.el (blink-matching-paren-distance):
    Cambia el valor por defecto a 12.000.

1993-05-24 Richard Stallman <rms@gnu.org>

    * vc.el (minor-mode-map-alist): No usar si es nulo.
    (vc-cancel-version): Doc fix.

Una entrada puede describir varios cambios; cada cambio debe tener su propio artículo, o su propia línea en un artículo. Normalmente debe haber una línea en blanco entre los elementos. Cuando los elementos estén relacionados (partes del mismo cambio, en lugares diferentes), agrúpelos sin dejar una línea en blanco entre ellos.

Al final del archivo de registro de cambios debe poner un aviso de copyright y un aviso de permiso. He aquí un ejemplo:

Copyright 1997, 1998 Free Software Foundation, Inc.
Se permite la copia y distribución de este archivo, con o sin modificaciones,
siempre que se conserven el aviso de copyright y este aviso.

Por supuesto, deberá sustituirlos por los años adecuados y el titular de los derechos de autor.

29.4 Buscar Referencias de Identificador

Un identificador es el nombre de una subunidad sintáctica del programa: una función, una subrutina, un método, una clase, un tipo de datos, una macro, etc. En un lenguaje de programación, cada identificador es un símbolo de la sintaxis del lenguaje. Los identificadores también se denominan etiquetas.

El desarrollo y el mantenimiento de programas requieren capacidades para encontrar rápidamente dónde se definió y se hizo referencia a cada identificador, para renombrar identificadores en todo el proyecto, etc. Estas capacidades también son útiles para encontrar referencias en modos principales distintos de los definidos para soportar lenguajes de programación. Por ejemplo, los capítulos, secciones, apéndices, etc. de un texto o un documento TeX también pueden tratarse como subunidades, y sus nombres pueden usarse como identificadores. En este capítulo, usamos el término «identificadores» para referirnos colectivamente a los nombres de cualquier tipo de subunidades, tanto en el código fuente de un programa como en otros tipos de texto.

Emacs proporciona una interfaz unificada para estas capacidades, llamada xref.

Para hacer su trabajo, xref necesita usar información y métodos específicos del modo principal. Qué archivos buscar para identificadores, cómo encontrar referencias a identificadores, cómo completar identificadores, todo esto y más es conocimiento específico del modo. xref delega las partes específicas del modo de su trabajo a un backend (aplicación del lado del servidor) proporcionado por el modo; también incluye valores por defecto para algunos de sus comandos, para aquellos modos que no proporcionan los suyos propios.

Un backend puede implementar sus capacidades de varias maneras. He aquí algunos ejemplos:

  1. Algunos modos mayores proporcionan métodos incorporados para buscar los símbolos del lenguaje. Por ejemplo, los símbolos de Emacs Lisp pueden identificarse buscando en el historial de carga de paquetes, mantenido por el intérprete Emacs Lisp, y consultando las cadenas de documentación incorporadas; el modo Emacs Lisp usa estas facilidades en su backend para permitir encontrar definiciones de símbolos. (Una desventaja de este tipo de backend es que sólo conoce las subunidades que se cargaron en el intérprete).

  2. Si Eglot está activado para el proyecto del búfer actual (véase 29.2 Trabajar con Proyectos) y el modo principal del búfer actual, Eglot consulta un programa servidor de idiomas externo y proporciona los datos suministrados por el servidor relativos a las definiciones de los identificadores del proyecto. Véase Características de Eglot en Eglot: El cliente LSP de Emacs.

  3. Un programa externo puede extraer referencias escaneando los archivos pertinentes y crear una base de datos con ellas. Un backend puede entonces acceder a esta base de datos siempre que necesite listar o buscar referencias. La distribución de Emacs incluye etags, un comando para etiquetar definiciones de identificadores en programas, que soporta muchos lenguajes de programación y otros modos principales, como HTML, extrayendo referencias en tablas de etiquetas. Véase 29.4.2.2 Crear Tablas de Etiquetas. Los modos principales para lenguajes soportados por etags pueden usar tablas de etiquetas como base para su backend. (Una desventaja de este tipo de backend es que las tablas de etiquetas deben mantenerse razonablemente actualizadas, reconstruyéndolas de vez en cuando).

29.4.1 Encontrar Identificadores

Esta subsección describe los comandos que encuentran referencias a identificadores y realizan varias consultas sobre identificadores. Cada una de estas referencias puede definir un identificador, por ejemplo, proporcionar la implementación de una subunidad de programa o el texto de una sección de un documento; o puede utilizar el identificador, por ejemplo, llamar a una función o a un método, asignar un valor a una variable, mencionar un capítulo en una referencia cruzada, etc.

29.4.1.1. Búsqueda de Identificadores

Lo más importante que le permite hacer xref es encontrar la definición de un identificador específico.

Alt-. (M-.)

Busca definiciones de un identificador (xref-find-definitions).

Ctrl-Alt-. patrón RETURN (C-M-. patrón RET)

Busca todos los identificadores cuyo nombre coincida con patrón (xref-find-apropos).

Ctrl-x 4. RETURN (C-x 4 . RET)

Busca definiciones de identificador, pero las muestra en otra ventana (xref-find-definitions-other-window).

Ctrl-x 5. RETURN (C-x 5 . RET)

Busca la definición del identificador y la muestra en un nuevo marco (xref-find-definitions-other-frame).

Alt-x xref-find-definitions-at-mouse (M-x xref-find-definitions-at-mouse)

Encuentra la definición de identificador con un clic del ratón.

Alt-, (M-,)

Vuelve al lugar donde invocó anteriormente a M-. y compañía (xref-go-back).

Ctrl-Alt-, (C-M-,)

Avanza hasta donde previamente invocó a M-, (xref-go-forward).

Alt-x xref-etags-mode (M-x xref-etags-mode)

Cambia xref para usar el backend etags.

M-. (xref-find-definitions) muestra la definición del identificador en el punto. Con un argumento prefijo, o si no hay identificador en el punto, pregunta por el identificador. (Si desea que siempre pregunte, personalice xref-prompt-for-identifier a t.)

Cuando se introduce el argumento identificador en M-., se pueden utilizar los comandos habituales de completado de minibúferes (ver 9.4 Completado), siendo los nombres de identificadores conocidos los candidatos a ser completados.

Como la mayoría de los comandos que pueden cambiar de búfer, xref-find-definitions tiene una variante que muestra el nuevo búfer en otra ventana, y otra que crea un nuevo marco para él. La primera es C-x 4 . (xref-find-definitions-other-window), y la segunda es C-x 5 . (xref-find-definitions-other-frame).

El comando xref-find-definitions-at-mouse funciona como xref-find-definitions, pero busca el nombre del identificador en o alrededor del lugar de un evento de ratón. Este comando está pensado para ser vinculado a un evento de ratón, como C-M-ratón-1, por ejemplo.

El comando C-M-. (xref-find-apropos) es como apropos para etiquetas (véase 11.4 Apropos). Muestra una lista de identificadores en la tabla de etiquetas seleccionada cuyos nombres coinciden con la expresión regular especificada. Esto es igual que M-., excepto que hace coincidir expreg de identificadores en lugar de coincidir nombres de símbolos como cadenas fijas. Por defecto, el comando muestra el búfer *xref*, como M-., pero puede mostrar una salida adicional personalizando la variable tags-apropos-additional-actions; consulte su documentación para más detalles.

Si cualquiera de los comandos anteriores encuentra más de una definición coincidente, abre por defecto el búfer *xref* mostrando los candidatos coincidentes (C-M-. siempre abre el búfer *xref* si encuentra al menos una coincidencia). (C-M-. siempre muestra el búfer *xref* si encuentra al menos una coincidencia.) Los candidatos se muestran normalmente en ese búfer como el nombre de un fichero y el/los identificador/es coincidente/s en ese fichero. En ese búfer, puede seleccionar cualquiera de los candidatos para su visualización, y dispone de varios comandos adicionales, descritos en Comandos disponibles en el búfer *xref*. Sin embargo, si el valor de la variable xref-auto-jump-to-first-definition es move, el primero de estos candidatos se selecciona automáticamente en el buffer *xref*, y si es t o show, el primer candidato se muestra automáticamente en su propia ventana; t también selecciona la ventana que muestra el primer candidato. El valor por defecto es nil, que sólo muestra los candidatos en el buffer *xref*, pero no selecciona ninguno de ellos.

Para volver a los lugares desde los que ha visualizado la definición, utilice M-, (xref-go-back). Salta hacia atrás al punto de la última invocación de M-.. Así puede encontrar y examinar la definición de algo con M-. y luego volver a donde estaba con M-,. M-, le permite volver sobre los pasos que dio hacia adelante en la historia de los lugares, hasta el primer lugar de la historia, donde invocó por primera vez M-., o a cualquier lugar intermedio.

Si anteriormente retrocedió demasiado con M-,, o desea volver a examinar un lugar desde el que retrocedió, puede utilizar C-M-, (xref-go-forward) para volver a avanzar. Esto es similar al uso de M-, excepto que no necesita en cada paso mover el punto hasta el identificador cuya definición desea consultar. C-M-, le permite volver sobre todos los pasos que dio hacia atrás en la historia de los lugares, hasta el último lugar de la historia, donde invocó M-,, o a cualquier lugar intermedio.

Algunos modos principales instalan facilidades de soporte xref que a veces pueden fallar al encontrar ciertos identificadores. Por ejemplo, en el modo Emacs Lisp (vea 28.9. Evaluación de Expresiones Emacs Lisp) M-. encontrará por defecto sólo funciones y variables de paquetes Lisp que estén cargados en la sesión Emacs actual o que estén autocargados (vea Autocarga en El Manual de Referencia de Emacs Lisp). Si M-. no encuentra algunos identificadores, puede intentar forzar a xref a usar el backend etags (vea 29.4 Buscar Referencias de Identificador). Para ello, active el modo menor Xref Etags (Etiquetas Xref) con M-x xref-etags-mode, y luego invoque M-. de nuevo. (Para que esto funcione, asegúrese de ejecutar etags para crear la tabla de etiquetas en el árbol de directorios de los archivos fuente; consulte 29.4.2.2 Crear Tablas de Etiquetas)

29.4.1.2 Comandos Disponibles en el Búfer *xref*

El modo especial XREF proporciona los siguientes comandos en el búfer xref:

RETURN (RET)
ratón-1

Muestra la referencia en la línea actual (xref-goto-xref). Con el argumento prefijo, también entierra el búfer *xref*.

ratón-2

Igual que ratón-1, pero haciendo que la ventana que muestra el búfer *xref* sea la ventana seleccionada (xref-select-and-show-xref).

n (n)

Pasa a la referencia siguiente y la muestra en la otra ventana (xref-next-line).

N (N)

Se desplaza a la primera referencia del siguiente grupo de referencia y la muestra en la otra ventana (xref-next-group).

p (p)
, (,)

Se desplaza a la referencia anterior y la muestra en la otra ventana (xref-prev-line).

p (p)

Se desplaza a la primera referencia del grupo de referencias anterior y la muestra en la otra ventana (xref-prev-group).

Ctrl-o (C-o)

Muestra la referencia en la línea actual en la otra ventana (xref-show-location-at-point).

r patrón RETURN reemplazo RETURN (r patrón RET reemplazo RET)

Realiza una consulta-reemplazo interactiva en las referencias que coinciden con el patrón (xref-query-replace-in-results), reemplazando la coincidencia con el reemplazo. Este comando sólo puede usarse en búferes *xref* que muestren todas las coincidencias para un identificador en todos los archivos relevantes. Véase 29.1.1.3 Conceptos de Control de Versiones.

g (g)

Actualiza el contenido del búfer *xref* (xref-revert-buffer).

Alt-, (M-,)

Sale de la ventana que muestra el búfer *xref*, y luego salta a la posición anterior de la pila Xref (xref-quit-and-pop-marker-stack).

q (q)

Sale de la ventana que muestra el búfer *xref* (xref-quit).

Además, dispone de los comandos de navegación habituales, como las teclas de flecha, C-n y C-p, para desplazarse por el búfer sin mostrar las referencias.

29.4.1.3. Buscar y Reemplazar con Identificadores

Los comandos de esta sección realizan varias operaciones de búsqueda y reemplazo en los propios identificadores o en los archivos que hacen referencia a ellos.

:kbd:-Alt-? (M-?)

Encuentra todas las referencias del identificador en el punto.

r (r)
Alt-x xref-query-replace-in-results RETURN reemplazo RETURN
(M-x xref-query-replace-in-results RET reemplazo RET)
Ctrl-u Alt-x xref-query-replace-in-results RETURN expreg RETURN reemplazo RETURN
(C-u M-x xref-query-replace-in-results RET expreg RET reemplazo RET)

Reemplaza interactivamente expreg con reemplazo en los nombres de todos los identificadores mostrados en el búfer *xref*.

Alt-x xref-find-references-and-replace RETURN desde RETURN a RETURN
(M-x xref-find-references-and-replace RET desde RET a RET)

Cambia interactivamente el nombre de todas las instancias del identificador desde al nuevo nombre a.

Alt-x tags-search RETURN expreg RETURN (M-x tags-search RET expreg* RET)

Busca por expreg a través de los archivos de la tabla de etiquetas seleccionada.

Alt-x tags-query-replace RETURN expreg RETURN reemplazo RETURN
(M-x tags-query-replace RET expreg RET reemplazo RET)

Efectúa un query-replace-regexp en cada archivo de la tabla de etiquetas seleccionada.

Alt-x fileloop-continue (M-x fileloop-continue)

Reinicia uno de los 2 últimos comandos anteriores, desde la ubicación actual del punto.

M-? busca todas las referencias para el identificador en el punto, preguntando por el identificador según sea necesario, con finalización. Dependiendo del backend actual (ver 29.4 Buscar Referencias de Identificador), el comando puede preguntar incluso si encuentra un identificador válido en el punto. Cuando se invoca con un argumento prefijo, siempre pregunta por el identificador. (Si desea que pregunte siempre, personalice el valor de la variable xref-prompt-for-identifier a t; o configúrela a nil para que pregunte sólo si no hay ningún identificador utilizable en el punto). El comando presenta entonces el búfer *xref* con todas las referencias al identificador, mostrando el nombre del archivo y la línea donde se hace referencia al identificador. Los comandos del modo XREF están disponibles en este búfer, véase 29.4.1.2 Comandos Disponibles en el Búfer *xref*.

Si el valor de la variable xref-auto-jump-to-first-xref es t, xref-find-references salta automáticamente al primer resultado y selecciona la ventana donde se muestra. Si el valor es show, se muestra el primer resultado, pero se deja seleccionada la ventana que muestra el búfer *xref*. Si el valor es move, el primer resultado se selecciona en el búfer *xref*, pero no se muestra. El valor por defecto es nil, que sólo muestra los resultados en el búfer *xref*, pero no selecciona ninguno de ellos.

r (xref-query-replace-in-results) lee una cadena de reemplazo, como una M-x query-replace-regexp ordinaria. Luego renombra los identificadores mostrados en el búfer *xref* en todos los lugares de todos los archivos donde estos identificadores son referenciados, de tal forma que su nuevo nombre sea reemplazo. Esto es útil cuando se renombran los identificadores como parte de la refactorización. Este comando debe ser invocado en el búfer *xref* generado por M-? Por defecto, el comando reemplaza el nombre completo de cada identificador con reemplazo, pero si se invoca con un argumento prefijo, el comando pide una expreg para emparejar los nombres de los identificadores, y reemplaza sólo las coincidencias de esa expreg en los nombres de los identificadores con reemplazo.

M-x xref-find-references-and-replace funciona de forma similar a xref-query-replace-in-results, pero es más conveniente cuando se desea renombrar un único identificador especificado por su nombre desde.

M-x tags-search lee una expreg usando el minibúfer, luego busca coincidencias en todos los archivos de la tabla de etiquetas seleccionada, un archivo a la vez. Muestra el nombre del archivo que se está buscando para que pueda seguir su progreso. En cuanto encuentra una coincidencia, tags-search regresa. Este comando requiere que las tablas de etiquetas estén disponibles (véase 29.4.2 Tablas de Etiquetas).

Después de encontrar una coincidencia con tags-search, probablemente quiera encontrar todas las demás. M-x fileloop-continue reanuda la búsqueda de etiquetas, encontrando una coincidencia más. Esto busca en el resto del búfer actual, seguido de los archivos restantes de la tabla de etiquetas.

M-x tags-query-replace realiza una única query-replace-regexp a través de todos los archivos de la tabla de etiquetas. Lee una expresión regular para buscar y una cadena con la que reemplazar, igual que la expresión regular M-x query-replace-regexp. Busca de forma similar a M-x tags-search, pero repetidamente, procesando las coincidencias según lo que introduzca. Consulte 16.10.4 Sustitución de Consultas, para obtener más información sobre la consulta reemplazar.

Puede controlar la distinción entre mayúsculas y minúsculas de los comandos de búsqueda de etiquetas personalizando el valor de la variable tags-case-fold-search. Por defecto se usa la misma configuración que el valor de case-fold-search (ver 16.9. Coincidencia Laxa Durante la Búsqueda).

Es posible recorrer todos los archivos de la tabla de etiquetas con una sola invocación de M-x tags-query-replace. Pero a menudo es útil salir temporalmente, lo que puede hacer con cualquier evento de entrada que no tenga un significado especial de reemplazo de consulta. Puede reanudar la consulta de sustitución posteriormente escribiendo M-x fileloop-continue; este comando reanuda el último comando de búsqueda o sustitución de etiquetas que haya realizado. Por ejemplo, para omitir el resto del archivo actual, puede escribir Alt-> fileloop-continue (M-> M-x fileloop-continue).

Tenga en cuenta que los comandos descritos anteriormente realizan búsquedas mucho más amplias que la familia xref-find-definitions. Los comandos xref-find-definitions sólo buscan definiciones de identificadores que coincidan con su cadena o expreg. Los comandos xref-find-references, tags-search, y tags-query-replace encuentran cada aparición del identificador o regexp, como hacen los comandos de búsqueda ordinarios y los comandos de reemplazo en el búfer actual.

Como alternativa a xref-find-references y tags-search, puede ejecutar grep como un subproceso y hacer que Emacs le muestre las líneas coincidentes una a una. Ver 28.4 Buscar con Grep en Emacs.

29.4.1.4 Consultas sobre Identificadores

Ctrl-Alt-i (C-M-i)
Alt-TAB (M-TAB)

Realiza el completado en el texto alrededor del punto, posiblemente usando la tabla de etiquetas seleccionadas si hay una cargada (completion-at-point).

Alt-x list-tags RETURN archivo RETURN
(M-x list-tags RET archivo RET)

Muestra una lista de los identificadores definidos en el archivo del programa con nombre archivo.

Ctrl-Alt-. expreg RETURN (C-M-. expreg RET)

Muestra una lista de todos los identificadores que coinciden con expreg (xref-find-apropos). Véase 29.4.1.1. Búsqueda de Identificadores.

Alt-x tags-next-file (M-x tags-next-file)

Visita los archivos registrados en la tabla de etiquetas seleccionada.

En la mayoría de los modos del lenguaje de programación, puede escribir Ctrl-Alt-i (C-M-i) o Alt-TAB (M-TAB, completion-at-point) para completar el símbolo en el punto. Algunos modos proporcionan un completado especializado para este comando adaptado al modo; para los que no, si hay una tabla de etiquetas cargada, este comando puede usarla para generar candidatos de completado. Véase 27.8 Completado de Nombres de Símbolos.

M-x list-tags lee el nombre de uno de los archivos cubiertos por la tabla de etiquetas seleccionada y muestra una lista de las etiquetas definidas en ese archivo. No incluya un directorio como parte del nombre del archivo a menos que el nombre del archivo registrado en la tabla de etiquetas incluya un directorio. Este comando sólo funciona con el backend etags (el programa que se encarga de las etiquetas etags), y requiere que esté disponible una tabla de etiquetas para el proyecto. Véase 29.4.2 Tablas de Etiquetas. Si se usa interactivamente, la etiqueta por defecto es el nombre de archivo del búfer actual.

M-x tags-next-file visita los archivos cubiertos por la tabla de etiquetas seleccionada. La primera vez que se llama, visita el primer archivo cubierto por la tabla. Cada vez que se ejecuta, se visita el siguiente archivo cubierto, a menos que se proporcione un argumento de prefijo, en cuyo caso se vuelve al primer archivo. Este comando requiere la selección de una tabla de etiquetas.

29.4.2 Tablas de Etiquetas

Una tabla de etiquetas registra las etiquetas [18] extraídas al escanear el código fuente de un determinado programa o un determinado documento. Las etiquetas extraídas de archivos generados hacen referencia a los archivos originales, en lugar de a los archivos generados que se escanearon durante la extracción de etiquetas. Algunos ejemplos de archivos generados son los archivos C generados a partir de archivos fuente Cweb, de un analizador Yacc o de definiciones del analizador Lex; archivos C preprocesados .i y archivos Fortran producidos mediante el preprocesamiento de archivos fuente .fpp.

Para producir una tabla de etiquetas, se ejecuta el comando de shell etags en un documento o en el archivo de código fuente. El programa etags escribe las etiquetas en un archivo de tabla de etiquetas, o archivo de etiquetas en abreviatura. El nombre convencional de un archivo de etiquetas es TAGS. Véase 29.4.2.2 Crear Tablas de Etiquetas. (También es posible crear una tabla de etiquetas usando uno de los comandos de otros paquetes que pueden producir tales tablas en el mismo formato).

Emacs usa las tablas de etiquetas a través del paquete etags como uno de los backends soportados por xref. Debido a que las tablas de etiquetas son producidas por el comando etags que es parte de una distribución Emacs, describimos las tablas de etiquetas en más detalle aquí.

La utilidad Ebrowse es similar a etags pero específicamente adaptada para C++. Véase Ebrowse en el Manual del Usuario de Ebrowse. El paquete Semantic proporciona otra forma de generar y usar etiquetas, aparte de la herramienta etags. Véase 27.10 Semántica.

29.4.2.1 Sintaxis de Etiquetas de Archivos Fuente

A continuación se muestra cómo se define la sintaxis de las etiquetas para los lenguajes más conocidos:

  • En código C, cualquier función C o typedef es una etiqueta, y también lo son las definiciones de struct, union y enum. Las definiciones de macros #define, #undef y las constantes enum también son etiquetas, a menos que especifique --no-defines al hacer la tabla de etiquetas. Del mismo modo, las variables globales son etiquetas, a menos que especifique --no-globals, y también lo son los miembros de struct, a menos que especifique --no-members. Usar --no-globals, --no-defines y --no-members puede hacer que el archivo de la tabla de etiquetas sea mucho más pequeño.

    Puede etiquetar declaraciones de funciones y variables externas además de definiciones de funciones dando la opción --declarations a etags.

  • En el código C++, además de todas las construcciones de etiquetas del código C, también se reconocen las funciones y variables miembro; también , a menos que use la opción --no-members. las definiciones de operadores tienen nombres de etiquetas como operator+. Si especifica la opción --class-qualify, las etiquetas para variables y funciones en clases se denominan class::variable y class::function. Por defecto, los métodos y miembros de las clases no se califican como tales, lo que permite identificar sus nombres en los fuentes con mayor precisión.

  • En el código Java, las etiquetas incluyen todas las construcciones reconocidas en C++, además de las construcciones interface, extends e implements. Las etiquetas para variables y funciones en las clases se denominan class.variable y class.function.

  • En los documentos LaTeX, los argumentos para \chapter, \section, \subsection, \subsubsection, \eqno, \label, \ref, \cite, \bibitem, \part, \appendix, \entry, \index, \def, \newcommand, \renewcommand, \newenvironment y \renewenvironment son etiquetas.

    Otros comandos también pueden hacer etiquetas, si los especifica en la variable de entorno TEXTAGS antes de invocar etags. El valor de esta variable de entorno debe ser una lista de nombres de comandos separados por dos puntos. Por ejemplo,

    TEXTAGS="micomando:miotrocomando"
    export TEXTAGS
    

    especifica (utilizando la sintaxis del shell Bourne) que los comandos \micomando y \miotrocomando también definen etiquetas.

  • En código Lisp, cualquier función definida con defun, cualquier variable definida con defvar o defconst, y en general el primer argumento de cualquier expresión que empiece por (def en la columna cero es una etiqueta. Como excepción, las expresiones de la forma (defvar foo) se tratan como declaraciones, y sólo se etiquetan si se da la opción --declarations.

  • En el código Scheme, las etiquetas incluyen cualquier cosa definida con def o con una construcción cuyo nombre empiece por def. También incluyen variables definidas con set! en el nivel superior del archivo.

También se admiten otros lenguajes:

  • En código Ada, las funciones, procedimientos, paquetes, tareas y tipos son etiquetas. Puede usar la opción --packages-only para crear etiquetas sólo para paquetes.

  • En Ada, se puede usar el mismo nombre para diferentes tipos de entidad (por ejemplo, para un procedimiento y para una función). Además, para cosas como paquetes, procedimientos y funciones, existe la especificación (es decir, la interfaz) y el cuerpo (es decir, la implementación). Para facilitar la elección de la definición deseada, los nombres de las etiquetas de Ada tienen sufijos que indican el tipo de entidad

/b

cuerpo del paquete.

/f

función.

/k

tarea.

/p

procedimiento.

/s

especificaciones del paquete.

/t

tipo.

Así, M-x find-tag RET bidule/b RET irá directamente al cuerpo del paquete bidule, mientras que M-x find-tag RET bidule RET sólo buscará cualquier etiqueta bidule.

  • En código ensamblador, las etiquetas que aparecen al principio de una línea, seguidas de dos puntos, son etiquetas.

  • En los archivos de entrada Bison o Yacc, cada regla define como etiqueta el no terminal que construye. Las partes del archivo que contienen código C se analizan como código C.

  • En código Cobol, las etiquetas son nombres de párrafos; es decir, cualquier palabra que comience en la columna 8 y vaya seguida de un punto.

  • En código Erlang, las etiquetas son las funciones, registros y macros definidos en el archivo.

  • En código Fortran, las funciones, subrutinas y datos de bloque son etiquetas.

  • En código Go, los paquetes, las funciones y los tipos son etiquetas.

  • En los archivos de entrada HTML, las etiquetas son el título y las cabeceras h1, h2, h3. También son etiquetas name= en las anclas y todas las apariciones de id=.

  • En los archivos de entrada Lua, todas las funciones son etiquetas.

  • En makefiles, los objetivos son etiquetas; además, las variables son etiquetas a menos que se especifique --no-globals.

  • En el código Objective C, las etiquetas incluyen definiciones Objective C para clases, categorías de clases, métodos y protocolos. Las etiquetas para variables y funciones en clases se denominan class::variable y class::function.

  • En código Pascal, las etiquetas son las funciones y procedimientos definidos en el archivo.

  • En código Perl, las etiquetas son los paquetes, subrutinas y variables definidas por las palabras clave package, sub, use constant, my y local. Use --globals si quiere etiquetar variables globales. Las etiquetas para subrutinas se denominan package::sub. El nombre para subrutinas definidas en el paquete por defecto es main::sub.

  • En código PHP, las etiquetas son funciones, clases y defines. Los vars también son etiquetas, a menos que use la opción --no-members.

  • En código PostScript, las etiquetas son las funciones.

  • En código Prolog, las etiquetas son predicados y reglas al principio de línea.

  • En código Python, def o class al principio de una línea generan una etiqueta.

  • En código Ruby, def o class o module al principio de una línea generan una etiqueta. Las constantes también generan etiquetas.

  • En código Rust, etiquetas cualquier cosa definida con fn, enum, struct o macro_rules!.

También puede generar etiquetas basadas en correspondencias expreg (véase 29.4.2.3 Expresiones Regulares (expreg) de Etags) para manejar otros formatos y lenguajes.

29.4.2.2 Crear Tablas de Etiquetas

El programa etags se puede usar para crear un archivo de tabla de etiquetas. Conoce la sintaxis de varios lenguajes, como se describe en 29.4.2.1 Sintaxis de Etiquetas de Archivos Fuente. A continuación se explica cómo ejecutar etags:

etags archivodeentrada…

El programa etags lee los archivos especificados y escribe una tabla de etiquetas llamada TAGS en el directorio de trabajo actual. Puede especificar opcionalmente un nombre de archivo diferente para la tabla de etiquetas usando la opción --output=file; especificando - como nombre de archivo imprime la tabla de etiquetas en la salida estándar. También puede anexar la tabla de etiquetas recién creada a un archivo existente usando la opción --append.

Si los archivos especificados no existen, etags busca versiones comprimidas de los mismos y las descomprime para leerlas. En MS-DOS, etags también busca nombres de archivo como mycode.cgz si se le da mycode.c en la línea de comandos y mycode.c no existe.

Si la tabla de etiquetas queda obsoleta debido a cambios en los archivos descritos en ella, puede actualizarla ejecutando de nuevo el programa etags. Si dicha tabla no registra ninguna etiqueta, o la registra para el archivo equivocado, Emacs no podrá encontrar esa definición hasta que actualice la tabla de etiquetas. Pero si la posición registrada en esta tabla se equivoca un poco (debido a otra edición), el Editor aún podrá encontrar la posición correcta, con un ligero retraso.

Por lo tanto, no es necesario actualizar la tabla de etiquetas después de cada edición. Debe actualizarla cuando defina nuevas etiquetas que desee que aparezcan en la lista, o cuando mueva definiciones de etiquetas de un archivo a otro, o cuando los cambios sean sustanciales.

Puede hacer que una tabla de etiquetas incluya otra tabla de etiquetas, pasando la opción --include=file a etags. En ese caso, etags cubrirá todos los archivos incluidos en el archivo de etiquetas incluido, así como los suyos propios.

Si especifica los archivos de origen con nombres de archivo relativos al ejecutar etags, el archivo de etiquetas contendrá nombres de archivo relativos al directorio en el que se escribió inicialmente el archivo de etiquetas. De este modo, puede mover todo un árbol de directorios que contenga tanto el archivo de etiquetas como los archivos fuente, y el archivo de etiquetas seguirá haciendo referencia correctamente a los archivos fuente. Sin embargo, si el archivo de etiquetas es - o está en el directorio /dev, los nombres de archivo se hacen relativos al directorio de trabajo actual. Esto es útil, por ejemplo, cuando se escriben las etiquetas en la salida estándar.

Cuando se usa un nombre de archivo relativo, no debe ser un enlace simbólico que apunte a un archivo de etiquetas en un directorio diferente, porque esto generalmente haría que los nombres de archivo no fueran válidos.

Si especifica nombres de archivo absolutos como argumentos para etags, el archivo de etiquetas contendrá nombres de archivo absolutos. De este modo, el archivo de etiquetas seguirá haciendo referencia a los mismos archivos aunque lo desplace, siempre que los archivos de origen permanezcan en el mismo lugar. Los nombres de archivo absolutos empiezan por /, o por device:/ en MS-DOS y MS-Windows.

Cuando quiera hacer una tabla de etiquetas a partir de un gran número de archivos, puede tener problemas para listarlos en la línea de comandos, porque algunos sistemas tienen un límite en su longitud. Puede eludir este límite diciéndole a etags que lea los nombres de los archivos desde su entrada estándar, escribiendo un guión en lugar de los nombres de los archivos, de esta forma

find . -name "*.[chCH]" -print | etags -

etags reconoce el idioma usado en un archivo de entrada basándose en su nombre y contenido. Primero intenta hacer coincidir el nombre y la extensión del archivo con los que se usan habitualmente con determinados lenguajes. Algunos lenguajes tienen intérpretes con nombres conocidos (por ejemplo, perl para Perl o pl para Prolog), así es que etags busca una especificación de intérprete de la forma #!interp en la primera línea de un archivo de entrada, y la compara con los intérpretes conocidos. Si nada de esto funciona, o si desea anular la detección automática del idioma, puede especificar el idioma explícitamente con la opción --language=nombre. Puede entremezclar estas opciones con los nombres de archivo; cada una se aplica a los nombres de archivo que le siguen. Especifique --language=auto para indicar a etags que vuelva a adivinar el idioma a partir de los nombres y el contenido de los archivos. Especifique --language=none para desactivar por completo el procesamiento específico del idioma; entonces etags reconoce las etiquetas únicamente mediante la coincidencia de expresiones regulares (consulte 29.4.2.3 Expresiones Regulares (expreg) de Etags). Esto es útil cuando un archivo de entrada usa un lenguaje no soportado por etags, y se quiere evitar que este recurra a Fortran y C como lenguajes por defecto.

La opción --parse-stdin=-nombre-archivo es útil sobre todo cuando se llama a etags desde programas. Se puede usar (sólo una vez) en lugar de un nombre de archivo en la línea de comandos. etags leerá de la entrada estándar y marcará las etiquetas producidas como pertenecientes al archivo nombre-archivo.

Para C y C++, si los archivos fuente no observan la convención de los Estándares de Codificación GNU de tener llaves ({ y }) en la columna cero sólo para definiciones de nivel superior, como funciones y definiciones de estructuras, le aconsejamos que use la opción --ignore-indentation, para evitar que etags interprete incorrectamente las llaves de cierre en la columna cero.

etags --help muestra la lista de lenguajes que etags conoce, y las reglas de nombre de archivo para adivinar ese lenguaje. También muestra una lista de todas las opciones disponibles de etags, junto con una breve explicación. Si va seguida de una o más opciones --language=lang, muestra información detallada sobre cómo se generan las etiquetas para lang.

29.4.2.3 Expresiones Regulares (expreg) de Etags

La opción --regex de etags permite que las etiquetas se reconozcan mediante coincidencias de expresiones regulares. Puede entremezclar esta opción con nombres de archivo; cada uno se aplica a los archivos fuente que le siguen. Si especifica varias opciones --regex, todas ellas se usan en paralelo. La sintaxis es:

--regex=[{lenguaje}]/etiquetaexpreg/[nombreexpreg/]modificadores

La parte esencial del valor de la opción es etiquetaexpregexp, la expreg para la coincidencia de etiquetas. Se usa siempre anclada, es decir, sólo coincide al principio de una línea. Si desea permitir etiquetas indentadas, use una expreg que coincida con el espacio en blanco inicial; comience con [ \t]*.

En estas expresiones regulares, \ entrecomilla el siguiente carácter, y todas las secuencias de escape de caracteres C son soportadas: \a para beep sonoro, \b para espacio posterior, \e para escape, \f para salto de página, \n para nueva línea, \r para retorno de carro, \t para tabulador, y \v para tabulador vertical. Además, \d representa el carácter DEL.

Idealmente, etiquetaexpreg no debería coincidir con más caracteres de los necesarios para reconocer lo que desea etiquetar. Si la sintaxis requiere que escriba etiquetaexpreg para que coincida con más caracteres además de la propia etiqueta, debería añadir un nombreexpreg, para seleccionar sólo la etiqueta. Esto permitirá a Emacs encontrar etiquetas de forma más precisa y completar nombres de etiquetas de forma más fiable. En nombre-expreg, es frecuentemente conveniente usar «back references» (ver 16.7 Barra Invertida en Expresiones Regulares) para agrupaciones entre paréntesis \( ... \) en etiquetaexpreg. Por ejemplo, \1 se refiere a la primera agrupación entre paréntesis. A continuación encontrará algunos ejemplos.

Los modificadores son una secuencia de cero o más caracteres que modifican la forma en que etags realiza la comparación. Una expreg sin modificadores se aplica secuencialmente a cada línea del archivo de entrada, distinguiendo entre mayúsculas y minúsculas. Los modificadores y sus significados son:

i

Ignora mayúsculas y minúsculas al comparar esta expreg.

m

Compara esta expresión regular con todo el archivo, de modo que es posible realizar comparaciones multilínea.

s

Compara esta expresión regular con todo el archivo y permite que . en etiquetaexpreg coincida con nuevas líneas.

La opción -R anula todas las expresiones regulares definidas por las opciones --regex precedentes. También se aplica a los nombres de archivo que le siguen. He aquí un ejemplo:

etags --regex=/reg1/i voo.doo --regex=/reg2/m \
    bar.ber -R --lang=lisp los.er

Aquí etags elige el lenguaje de análisis para voo.doo y bar.ber según su contenido. etags también usa reg1 para reconocer etiquetas adicionales en voo.doo, y tanto reg1 como reg2 para reconocer etiquetas adicionales en bar.ber. reg1 se comprueba con cada línea de voo.doo y bar.ber, sin distinguir entre mayúsculas y minúsculas, mientras que reg2 se comprueba en todo el archivo bar.ber, permitiendo coincidencias multilínea, sin distinguir entre mayúsculas y minúsculas. etags usa sólo las reglas de etiquetas de Lisp, sin coincidencias expreg especificadas por el Usuario, para reconocer etiquetas en los.er.

Puede restringir una opción --regex para que coincida sólo con archivos de un idioma determinado usando el prefijo opcional {language}. (etags --help imprime la lista de idiomas reconocidos por etags.) Esto es particularmente útil cuando se almacenan muchas expresiones regulares predefinidas para etags en un archivo. El siguiente ejemplo etiqueta las macros DEFVAR en los archivos fuente de Emacs, sólo para el lenguaje C:

--regex='{c}/[ \t]*DEFVAR_[A-Z_ \t(]+"\([^"]+\)"/\1/'

Cuando se tienen expresiones regulares complejas, se puede almacenar la lista de ellas en un archivo. La siguiente sintaxis de opción indica a etags que lea dos archivos de expresiones regulares. Las expresiones regulares contenidas en el segundo archivo se comparan sin tener en cuenta mayúsculas y minúsculas.

--regex=@case-sensitive-file --ignore-case-regex=@ignore-case-file

Un archivo expreg para etags contiene una expresión regular por línea. Se ignoran las líneas vacías y las que empiezan por espacio o tabulador. Cuando el primer carácter de una línea es @, etags asume que el resto de la línea es el nombre de otro archivo de expresiones regulares; así, un archivo de este tipo puede incluir otro archivo. Todas las demás líneas se consideran expresiones regulares. Si el primer texto sin espacio en blanco de la línea es --, esa línea es un comentario.

Por ejemplo, podemos crear un archivo llamado ´emacs.tags`` con el siguiente contenido:

    -- Esto es para archivos fuente C de GNU Emacs
{c}/[ \t]*DEFVAR_[A-Z_ \t(]+"\([^"]+\)"/\1/

y luego usarlo de esta manera:

etags --regex=@emacs.tags *.[ch] */*.[ch]

He aquí algunos ejemplos más. Las expresiones regulares se entrecomillan para protegerlas de la interpretación del shell.

* Etiqueta archivos Octave:
     etags --language=none \
           --regex='/[ \t]*function.*=[ \t]*\([^ \t]*\)[ \t]*(/\1/' \
           --regex='/###key \(.*\)/\1/' \
           --regex='/[ \t]*global[ \t].*/' \
           *.m

Tenga en cuenta que las etiquetas no se generan para los scripts, por lo que tendrá que añadir una línea por sí mismo de la forma ###tecla nombredelscript si desea saltar a él.

Etiqueta archivos Tcl:

etags --language=none --regex='/proc[ \t]+\([^ \t]+\)/\1/' *.tcl

Etiqueta archivos VHDL:

etags --language=none \
      --regex='/[ \t]*\(ARCHITECTURE\|CONFIGURATION\) +[^ ]* +OF/' \
      --regex='/[ \t]*\(ATTRIBUTE\|ENTITY\|FUNCTION\|PACKAGE\
      \( BODY\)?\|PROCEDURE\|PROCESS\|TYPE\)[ \t]+\([^ \t(]+\)/\3/'

29.4.3. Seleccionar una Tabla de Etiquetas

Emacs tiene en cualquier momento como máximo una tabla de etiquetas seleccionada. Todos los comandos para trabajar con tablas de etiquetas usan primero la seleccionada. Para seleccionar una tabla de etiquetas, escriba Alt-x visit-tags-table (M-x visit-tags-table), que lee el nombre del archivo de la tabla de etiquetas como argumento, con TAGS por defecto en el primer directorio que contenga un archivo llamado TAGS encontrado al buscar recursivamente hacia arriba desde el directorio por defecto.

Emacs no lee realmente los contenidos de la tabla de etiquetas hasta que intenta usarlas; todo lo que hace visit-tags-table es almacenar el nombre del archivo en la variable tags-file-name, y no mucho más. El valor inicial de la variable es nil; ese valor le dice a todos los comandos para trabajar con tablas de etiquetas que deben preguntar por un nombre de archivo de tabla de etiquetas para usar.

Además de la tabla de etiquetas seleccionada, Emacs mantiene disponible la lista de varias tablas de etiquetas que usa juntas. Por ejemplo, si esta trabajando en un programa que usa una librería, puede que desee tener disponibles las tablas de etiquetas tanto del programa como de la librería, para que Emacs pueda encontrar fácilmente los identificadores de ambos. Si la tabla de etiquetas seleccionada no tiene el identificador o no menciona el archivo fuente que necesita un comando de etiquetas, el comando intentará usar todas las demás tablas de etiquetas de la lista actual de dicha tabla.

Usar visit-tags-table para cargar una nueva tabla de etiquetas cuando otra tabla de etiquetas ya está cargada le da una opción: puede añadir la nueva tabla de etiquetas a la lista actual de tablas de etiquetas, o descartar la lista actual y comenzar una nueva lista. Si inicia una nueva lista, se usará la nueva tabla de etiquetas en lugar de otras. Si añade la nueva tabla a la lista actual, se usa igual que las demás.

Puede especificar una lista precisa de tablas de etiquetas estableciendo la variable tags-table-list en una lista de nombres de directorio, de la siguiente manera:

(setq tags-table-list
  '("~/.emacs.d" "/usr/local/lib/emacs/src"))

Esto le dice a los comandos tags que busquen en los archivos TAGS en su directorio ~/.emacs.d y en el directorio /usr/local/lib/emacs/src. El orden depende del archivo en el que se encuentre y de la tabla de etiquetas que mencione ese archivo.

No establezca al mismo tiempo tags-file-name y tags-table-list.

29.5 Entorno de Desarrollo Emacs (EDE)

EDE (Emacs Development Environment, Entorno de Desarrollo de Emacs) es un paquete que simplifica la tarea de crear, construir y depurar grandes programas con Emacs. Proporciona algunas de las características de un IDE, o Entorno de Desarrollo Integrado, en Emacs.

Esta sección proporciona una breve descripción del uso de EDE. Para más detalles, ver EDE en Emacs Development Environment.

EDE está implementado como un modo menor global (ver 24.2 Modos Menores). Para activarlo, escriba Alt-x global-ede-mode (M-x global-ede-mode) o haga clic en el elemento Project Support (EDE) (Gestion de Proyecto) del menú Tools (Herramientas). También puede activar EDE cada vez que inicie Emacs, añadiendo la siguiente línea a su archivo de inicialización:

(global-ede-mode t)

Al activar EDE se añade un menú llamado Development (Desarrollo) a la barra de menús. Muchos comandos de EDE, incluidos los que se describen a continuación, pueden invocarse desde este menú.

EDE organiza los archivos en proyectos, que corresponden a árboles de directorios. La raíz del proyecto es el directorio superior de un proyecto. Para definir un nuevo proyecto, visite un archivo en la raíz del proyecto deseado y escriba Alt-x ede-new (M-x ede-new). Este comando pide un tipo de proyecto, que se refiere al método subyacente que EDE usará para gestionar el proyecto (ver EDE en el Entorno de Desarrollo Emacs). Los tipos de proyecto más comunes son Make, que usa Makefiles, y Automake, que usa GNU Automake (ver Automake en Automake). En ambos casos, EDE también crea un archivo llamado Project.ede, que almacena información sobre el proyecto.

Un proyecto puede contener uno o más archivos de destino (objetivos). Un objetivo puede ser un archivo objeto, un programa ejecutable o cualquier otro tipo de archivo, que se construye a partir de uno o varios de los archivos del proyecto.

Para añadir un nuevo objetivo (o destino) a un proyecto, escriba Ctrl-c .t (C-c . t, M-x ede-new-target). Este comando también pregunta si desea añadir el archivo actual a ese destino, lo que significa que el objetivo se construirá a partir de ese archivo. Después de definir un objetivo, puede añadirle más archivos escribiendo Ctrl-c .a (C-c . a, ede-add-file).

Para construir un objetivo, escriba Ctrl-c . (C-c ., cede-compile-target). Para compilar todos los objetivos del proyecto, escriba Ctrl-c .C (C-c . C, ede-compile-project). EDE usa los tipos de archivo para deducir cómo debe construirse el objetivo.

29.6 Fusión de Archivos con Emerge

No es raro que los programadores se confundan y modifiquen el mismo programa en dos versiones diferentes. Para recuperarse de esta confusión, es necesario fusionar las dos versiones. Emerge facilita esta tarea. Para conocer otras formas de comparar archivos, consulte 19.9 Comparación de Archivos, y Ediff en El Manual de Ediff.

29.6.1 Descripción General de Emerge

Para iniciar Emerge, ejecute uno de estos cuatro comandos:

Alt-x emerge-files (M-x emerge-files)

Fusiona dos archivos especificados.

Alt-x emerge-files-with-ancestor (M-x emerge-files-with-ancestor)

Fusiona dos archivos especificados, con referencia a un archivo antecesor común.

Alt-x emerge-buffers (M-x emerge-buffers)

Fusiona dos búferes.

Alt-x emerge-buffers-with-ancestor (M-x emerge-buffers-with-ancestor)

Fusiona dos búferes con referencia a un mismo archivo antecesor en un tercer búfer.

Los comandos Emerge comparan dos archivos o búferes, y muestran la comparación en tres búferes: uno para cada texto de entrada (el búfer A y el búfer B), y uno (el búfer de fusión) donde tiene lugar la fusión. El búfer de fusión muestra el texto fusionado completo, no sólo las diferencias. Siempre que los dos textos de entrada difieran, puede elegir cuál de ellos incluir en el búfer de fusión.

Los comandos de Emerge que toman datos de búferes existentes sólo usan las partes accesibles de esos búferes, si están reducidos. Consulte 15.5 Estrechamiento.

Si se dispone de una versión antecesora común, de la que derivan los dos textos que se van a fusionar, Emerge puede usarla para determinar qué alternativa es la correcta. Siempre que una versión actual coincida con la antecesora, Emerge presume que la otra versión actual es un cambio deliberado que debe mantenerse en la versión fusionada. Use los comandos with-ancestor si desea especificar un texto antecesor común. Estos comandos leen tres nombres de archivo o búfer: la variante A, la variante B y el ancestro común.

Una vez realizada la comparación y preparados los búferes, comienza la fusión interactiva. Puede controlar la fusión escribiendo comandos especiales en el búfer de fusión (véase 29.6.4 Comandos de Fusión). Para cada serie de diferencias entre los textos de entrada, puede elegir cuál de ellos desea conservar, o editar ambos a la vez.

El búfer de fusión usa un modo principal especial, el modo Emerge, con comandos para hacer estas elecciones. Pero también puede editar el búfer con comandos Emacs ordinarios.

En un momento dado, la atención de Emerge se centra en una diferencia en particular, llamada diferencia seleccionada. Esta diferencia se marca en los tres búferes de la siguiente forma:

vvvvvvvvvvvvvvvvvvvv
texto que difiere
^^^^^^^^^^^^^^^^^^^^

Emerge numera todas las diferencias secuencialmente y la línea de modo muestra siempre el número de la diferencia seleccionada.

Normalmente, el búfer de fusión comienza con la versión A del texto. Pero cuando la versión A de una diferencia coincide con el ancestro común, entonces se prefiere inicialmente la versión B para esa diferencia.

Emerge deja el texto fusionado en el búfer de fusión cuando sale. En ese momento, puede guardarlo en un archivo con C-x C-w. Si da un argumento numérico a emerge-files o emerge-files-with-ancestor, lee el nombre del archivo de salida usando el minibúfer. (Este es el último nombre de archivo que leen esos comandos.) Luego, al salir de Emerge se guarda el texto fusionado en el archivo de salida.

Normalmente, los comandos de Emerge guardan el búfer de salida en su archivo al salir. Si aborta Emerge con C-], el comando Emerge no guarda el búfer de salida, pero puede guardarlo Usted mismo si lo desea.

29.6.2 Submodos de Emerge

Puede elegir entre dos modos para dar órdenes de fusión: Modo Rápido (Fast Mode) y Modo Edición (Edition Mode). En el modo Rápido, los comandos de fusión básicos son caracteres simples, pero los comandos Emacs ordinarios están desactivados. Esto es conveniente si sólo usas comandos de fusión. En modo Edición, todos los comandos merge empiezan con la tecla prefijo Ctrl-c Ctrl-c (C-c C-c), y los comandos normales de Emacs también están disponibles. Esto permite editar el búfer de fusión, pero ralentiza las operaciones Emerge.

Use e para cambiar al modo Edición, y C-c C-c f para cambiar al modo Rápido. La línea de modo indica los modos Editar y Rápido con E y F.

Emerge tiene dos submodos adicionales que afectan al funcionamiento de determinados comandos de fusión: Modo de Avance Automático (Auto Advance mode) y Modo de Omitir Prefijos (Skip Prefers mode).

Si el modo Avance Automático está activado, los comandos a y b avanzan a la siguiente diferencia. Esto le permite realizar la fusión más rápidamente siempre que elija simplemente una de las alternativas de la entrada. La línea de modo indica el modo Avance Automático con A.

Si el modo Omitir preferencias está activado, los comandos n y p omiten las diferencias en los estados «prefer-A» y «prefer-B» (véase 29.6.3 Estado de una Diferencia). Por lo tanto, sólo verá las diferencias para las que ninguna de las versiones se considera correcta. La línea de modo indica el modo Prefiere Omitir (Skip Prefers mode) con S. Este modo sólo es relevante cuando existe un antecesor.

Use el comando s a (emerge-auto-advance) para activar o desactivar el modo Auto Advance. Use s s (emerge-skip-prefers) para activar o desactivar el modo Omitir Preferencias (Skip Prefers). Estos comandos activan el modo con un argumento positivo, lo desactivan con un argumento negativo o cero, y conmutan el modo sin argumento.

29.6.3 Estado de una Diferencia

En el búfer de fusión, una diferencia se marca con líneas de caracteres v y ^. Cada diferencia tiene uno de estos siete estados:

A

La diferencia es que muestra la versión A. El comando a siempre produce este estado; la línea de modo lo indica con A.

B

La diferencia es que muestra la versión B. El comando b siempre produce este estado; la línea de modo lo indica con B.

default-A
default-B

La diferencia muestra el estado A o el B por defecto, porque no ha hecho ninguna elección. Todas las diferencias comienzan en el estado por defecto A (y por tanto el búfer de fusión es una copia del búfer A), excepto aquellas para las que se prefiere una alternativa (véase más adelante).

Cuando se selecciona una diferencia, su estado cambia de: «por defecto-A» (default-A) o «por defecto-B» (default-B) a: «simple A» (plain A) o «simple B» (plain B). Así, la diferencia seleccionada nunca tiene el estado «por defecto-A» (default-A) o «por defecto-B» (default-B), y estos estados nunca se muestran en la línea de modo.

El comando d a elige a: «por defecto-A» (default-A) como estado por defecto, y d b elige a: «por defecto-B» (default-B). Este valor predeterminado elegido se aplica a todas las diferencias que nunca ha seleccionado y para las que no se prefiere ninguna alternativa. Si se desplaza secuencialmente por la fusión, las diferencias que no ha seleccionado son las que siguen a la seleccionada. Así, mientras se mueve secuencialmente, puede hacer que la versión A sea la predeterminada para algunas secciones del búfer de fusión y la versión B la predeterminada para otras, usando d a y d b entre secciones.

prefer-A
prefer-B

La diferencia muestra el estado A o B porque es el preferido. Esto significa que no se ha hecho una elección explícita, pero una alternativa parece probablemente correcta porque la otra alternativa concuerda con el ancestro común. Así, cuando el búfer A concuerda con el antepasado común, se prefiere la versión B, porque es probable que sea la que se modificó realmente.

Estos dos estados se muestran en la línea de modo como A* y B*.

combined

La diferencia está mostrando una combinación de los estados A y B, como resultado de los comandos x c o x C.

Una vez que la diferencia está en este estado, los comandos a y b no le hacen nada a menos que les des un argumento numérico.

La línea de modo muestra este estado como comb.

29.6.4 Comandos de Fusión

Estos son los comandos Merge para el modo Rápido (Fast mode); en modo Edición (Edit mode), precedalos co la combinación de teclas Ctrl-c Ctrl-c (C-c C-c):

p (p)

Selecciona la diferencia anterior.

n (n)

Selecciona la siguiente diferencia.

a (a)

Elige la «versión A» de esta diferencia.

b (b)

Elige la «versión B» de esta diferencia.

Ctrl-u nj (C-u n j)

Selecciona el número de diferencia n.

. (.)

Selecciona el punto que contiene la diferencia.

q (q)

Sale y termina la fusión.

Ctrl-] (C-])

Aborta-sale de la fusión y no guarda la salida.

f (f)

Entra en modo Rápido (Fast mode). (En el modo Edición (Edit mode), en realidad es C-c C-c f).

e (e)

Entra en el modo Edición.

l (l)

Recentra (como C-l) las tres ventanas. Con un argumento, restablece la visualización de tres ventanas por defecto.

- (-)

Especifica parte de un argumento numérico prefijo.

digit

Especifica también parte de un argumento numérico prefijado.

daxsy (d a)

Elige la «versión A» como predeterminada de aquí abajo en el búfer de fusión.

db (d b)

Elige la «versión B» por defecto de aquí abajo en el búfer de fusión.

ca (c a)

Copia la «versión A» de esta diferencia en el anillo de muertes.

cb (c b)

Copia la «versión B» de esta diferencia en el anillo de muertes.

ia (i a)

Inserta la «versión A» de esta diferencia en el punto.

ib (i b)

Inserta la «versión B» de esta diferencia en el punto.

m (m)

Coloca punto y marca alrededor de la diferencia.

^ (^)

Desplaza las tres ventanas hacia abajo (como M-v).

v (v)

Desplaza las tres ventanas hacia arriba (como C-v).

< (<)

Desplaza las tres ventanas hacia la izquierda (como C-x <).

> (>)

Desplaza las tres ventanas hacia la derecha`como C-x >).

| (|)

Restablece el desplazamiento horizontal en las tres ventanas.

x1 (x 1)

Reduce la ventana de fusión a una línea. (Use C-u l para restaurarla a su tamaño completo).

xc (x c)

Combina las dos versiones de esta diferencia (véase 29.6.6 Combinar las Dos Versiones).

xf (x f)

Muestra los nombres de los archivos/búferes en los que Emerge está operando, en una ventana de Ayuda. (Use C-u l para restaurar ventanas).

xj (x j)

Une esta diferencia con la siguiente. (C-u x j une esta diferencia con la anterior).

xs (x s)

Divide esta diferencia en dos diferencias. Antes de usar este comando, sitúe un punto en cada uno de los tres búferes en el lugar donde desea dividir la diferencia.

xt (x t)

Suprime las líneas idénticas de la parte superior e inferior de la diferencia. Estas líneas se producen cuando las versiones A y B son idénticas pero difieren de la versión antecesora.

29.6.5. Salir de Emerge

El comando q (emerge-quit) finaliza la fusión, almacenando los resultados en el archivo de salida si especificó uno. Restaura los búferes A y B a sus contenidos apropiados, o los mata si fueron creados por Emerge y no los ha cambiado. También desactiva los comandos de Emerge en el búfer de fusión, ya que ejecutarlos más tarde podría dañar el contenido de los distintos búferes.

C-] aborta la fusión. Esto significa salir sin escribir el archivo de salida. Si no se ha especificado un archivo de salida, no hay diferencia entre abortar y finalizar la fusión.

Si el comando Emerge fue llamado desde otro programa Lisp, entonces su valor de retorno es t para una finalización exitosa, o nil si aborta.

29.6.6 Combinar las Dos Versiones

A veces querrá mantener ambas alternativas para una diferencia en particular. Para ello, use x c, que edita el búfer de fusión de la siguiente manera:

#ifdef NEW
versión del búfer B
#else /* no NEW */
versión del búfer A
#endif /* no NEW */

Aunque este ejemplo muestra condicionales del preprocesador C delimitando las dos versiones alternativas, puede especificar las cadenas a usar estableciendo la variable emerge-combine-versions-template a una cadena de su elección. En la cadena, %a dice dónde poner la versión A, y %b dice dónde poner la versión B. La configuración por defecto, que produce los resultados mostrados arriba, tiene este aspecto:

"#ifdef NEW\n%b#else /* not NEW */\n%a#endif /* not NEW */\n"

29.6.7 Puntos Más Delicados de Emerge

Durante la fusión, no debe intentar editar los búferes A y B por su propia cuenta. Emerge los modifica temporalmente, pero al final los vuelve a dejar como estaban.

Puede realizar cualquier número de fusiones a la vez, pero no use ningún búfer como entrada para más de una fusión a la vez, ya que los cambios temporales realizados en estos búferes se interpondrían entre sí.

Iniciar Emerge puede llevar mucho tiempo porque necesita comparar los archivos completamente. Emacs no puede hacer nada más hasta que diff termine. Quizás en el futuro alguien cambie Emerge para que haga la comparación en segundo plano cuando los archivos de entrada sean grandes, entonces podría seguir haciendo otras cosas con Emacs hasta que Emerge esté listo para aceptar comandos.

Después de configurar la fusión, Emerge ejecuta el gancho emerge-startup-hook. Ver 50.2.2 Ganchos (Hooks).

29.7 Referencia de Fallos

La mayoría de los proyectos con un cierto número de Usuarios registran los informes de fallos en algún software de seguimiento de incidencias que asigna a cada informe un número o identificador único y corto. Éstos se usan para hacer referencia a un fallo determinado, por ejemplo, en un comentario del código fuente sobre el código que corrige algún fallo, en archivos de documentación o en discusiones en alguna lista de correo o canal IRC.

Los modos menores bug-reference-mode y bug-reference-prog-mode resaltan dichas referencias de fallo y hacen posible seguirlas hasta el informe de fallo correspondiente en el gestor de incidencias del proyecto. bug-reference-prog-mode`` es una variante de bug-reference-mode que resalta las referencias de fallo sólo dentro de los comentarios y cadenas del código fuente.

Para funcionar, el modo bug-reference necesita conocer la sintaxis de las referencias a fallos (bug-reference-bug-regexp), y la URL del gestor donde se pueden buscar los informes de fallos (bug-reference-url-format). Dado que estos son típicamente diferentes de un proyecto a otro, tiene sentido especificarlos en ver 50.2.5 Variables Locales por Directorio o ver 50.2.4. Variables locales en Archivos.

Por ejemplo, supongamos que en nuestro proyecto, normalmente escribimos referencias a informes de fallos como bug#1234, o Bug-1234 y que la página de este fallo en el rastreador de incidencias es https://project.org/issues/1234, entonces esta sección de variables locales serviría.

;; Variables Locales:
;; bug-reference-bug-regexp: "\\([Bb]ug[#-]\\([0-9]+\\)\\)"
;; bug-reference-url-format: "https://project.org/issues/%s"
;; End:

La cadena capturada por el primer grupo (bug-reference-bug-regexp) define los límites de la superposición que crea bug-reference, es decir, la parte que se resalta y sobre la que se puede hacer clic.

La cadena capturada por el segundo grupo expreg en bug-reference-bug-regexp se usa para reemplazar la plantilla %s en bug-reference-url-format.

Tenga en cuenta que bug-reference-url-format también puede ser una función con el fin de atender a escenarios más complejos, por ejemplo, cuando diferentes partes de la referencia del fallo tienen que ser usadas para distinguir entre incidencias y solicitudes de fusión que resultan en diferentes URLs.

Configuración Automática

Si bug-reference-mode está activado, bug-reference-mode-hook se ha ejecutado y, bug-reference-bug-regexp junto con bug-reference-url-format: ambos aún están sin establecer, intentará configurar valores adecuados para estas dos variables por sí mismo llamando a las funciones en bug-reference-auto-setup-functions una tras otra hasta que uno sea capaz de establecer las variables.

Ahora mismo, hay tres tipos de funciones de configuración.

  1. Ajustes para archivos de versión controlada configurables mediante las variables bug-reference-forge-alist, y bug-reference-setup-from-vc-alist. Los valores por defecto son capaces de configurar proyectos GNU donde https://debbugs.gnu.org se usa como gestor de incidencias y las incidencias se referencian normalmente como bug#13 (pero también se consideran muchas notaciones diferentes), y varios tipos de software moderno como GitLab, Gitea, SourceHut, o GitHub. Si despliega una instancia autoalojada de este tipo de comunidad de programadores, la forma más fácil de informar a bug-reference sobre ella es a través de bug-reference-forge-alist.

  2. La configuración para el correo electrónico se obtiene a partir de los nombres de las carpetas/buzones de correo y los valores de las cabeceras de correo, configurables mediante la variable bug-reference-setup-from-mail-alist. El lector de noticias y correo integrado 35 Correo Electrónico y Noticias de Usenet con Gnus.

  3. Configuración de canales IRC configurable mediante la variable bug-reference-setup-from-irc-alist. Los clientes IRC integrados Rcirc, Ver Rcirc en el Manual de Rcirc, y ERC, Ver ERC en el Manual de ERC, están soportados.

Para casi todos estos modos, basta con activar el modo de referencia de fallos (bug-reference-mode), sólo Rmail requiere una configuración ligeramente diferente.

;; Usa la configuración basada en VC si el archivo está bajo control de versiones.
(add-hook 'prog-mode-hook #'bug-reference-prog-mode)

;; Gnus (resumen y búferes de artículos)
(add-hook 'gnus-mode-hook #'bug-reference-mode)

;; Rmail
(add-hook 'rmail-show-message-hook #'bug-reference-mode-force-auto-setup)

;; Rcirc
(add-hook 'rcirc-mode-hook #'bug-reference-mode)

;; ERC
(add-hook 'erc-mode-hook #'bug-reference-mode)

En el caso de Rmail, en lugar del gancho de modo, hay que usar el gancho rmail-show-message-hook en combinación con la función bug-reference-mode-force-auto-setup que activa bug-reference-mode y fuerza la configuración automática. La razón es que con Rmail todos los mensajes residen en el mismo búfer pero la configuración debe realizarse cada vez que se muestra otro mensaje.

Añadir Soporte para Paquetes de Terceros

Añadir soporte para la autoconfiguración de «bug-reference» suele ser bastante sencillo: escriba una función de configuración de cero argumentos que recopile la información necesaria (por ejemplo, los valores de cabecera de correo List-Id/To/From/Cc en el caso de un MUA), y luego llame a una de las siguientes funciones de ayuda

  • bug-reference-maybe-setup-from-vc que realiza la configuración según bug-reference-setup-from-vc-alist,

  • bug-reference-maybe-setup-from-mail que hace la configuración según bug-reference-setup-from-mail-alist,

  • y bug-reference-maybe-setup-from-irc que hace la configuración según bug-reference-setup-from-irc-alist.

Una función de configuración debe devolver un valor no nulo si puede configurar el modo de referencia de fallo, lo que ocurre si lo último que hace la función es llamar a una de las funciones de ayuda anteriores.

Por último, la función de configuración debe añadirse a bug-reference-auto-setup-functions.

Tenga en cuenta que estas funciones de configuración automática deberían comprobar como primer paso si son aplicables, por ejemplo, comprobando el valor de major-mode.

Integración con el Paquete debbugs

Si las incidencias de su proyecto se rastrean en el servidor https://debbugs.gnu.org, puede examinar y responder a los informes directamente en Emacs usando el paquete debbugs, que puede descargarse a través del menú de paquetes (consulte 49 Paquetes Emacs Lisp). Este paquete añade el modo menor debbugs-browse-mode, que puede activarse sobre bug-reference-mode y bug-reference-prog-mode como sigue:

(add-hook 'bug-reference-mode-hook 'debbugs-browse-mode)
(add-hook 'bug-reference-prog-mode-hook 'debbugs-browse-mode)