Idealmente, me gustaría poder almacenar todo el contenido de mi .emacs.d
directorio y hacer que "funcione" en cualquier Emacs en el que lo cargue, pero aún así aprovechar las características del entorno específico, como los sistemas de ventanas GUI.
No estoy buscando una enciclopedia de características incompatibles. Solo me gustaría saber cómo verificar las características, el sistema operativo, la versión, los gráficos, etc., y cómo aprovecharlos sin romper el código para otras configuraciones.
¿Qué técnicas básicas puedo usar para escribir Elisp que funcione en múltiples versiones de Emacs comunes en la naturaleza (por ejemplo, 22.x +) y en múltiples plataformas subyacentes (por ejemplo, OSX, Linux, Windows y otras * nix), mientras aprovecho la plataforma y características específicas de la versión donde corresponda?
fuente
window-system
, etc., se pueden responder razonablemente aquí.forward-char
y quiere que se cambie la pregunta para preguntar en suscroll-up
lugar. Si el OP quiere compatibilidad con Emacs 22+, déjelo en paz. Y no, la pregunta planteada no es solo acerca de OS X. Y sí, todavía hay muchas personas que usan versiones anteriores de Emacs (algunas incluso mayores de 22 años, FWIW).Respuestas:
Elisp es un lenguaje interpretado. Puede poner código específico de la versión en su
.emacs
, pero protegerlo probando en el momento de la carga que está funcionando en la versión correcta.Este código funcionará en todas las versiones porque
(shiny-new-feature)
solo se evalúa cuando(is-new-feature-available)
devuelve verdadero. Gran parte de esta respuesta está dedicada a cómo implementarla(is-new-feature-available)
.Lidiando con diferentes conjuntos de características
Es mejor probar si hay una función disponible que probar la versión de Emacs. A veces, la función puede estar disponible como un paquete opcional. Si desea ejecutar código en XEmacs u otra variante de Emacs, es posible que haya adquirido las mismas características en diferentes versiones. Use la función
boundp
para probar si una variable está disponible yfboundp
para probar si una función está disponible.Por ejemplo, el siguiente fragmento vincula una tecla para alternar
visual-line-mode
si está disponible, y de lolonglines-mode
contrario.A veces, en lugar de probar la función, es más fácil ejecutar un pequeño fragmento de código e ignorar cualquier error debido a funciones indefinidas, argumentos no válidos, etc. No haga esto para grandes cantidades de código, ya que esto hará que su código sea muy Difícil de depurar.
Por ejemplo, no quiero ver una barra de herramientas. Las versiones anteriores de Emacs no los tenían en absoluto. GNU Emacs y XEmacs agregaron esa característica de diferentes maneras y la convirtieron en la predeterminada. Así es como los apago. La
set-specifier
función es específica de XEmacs ydefault-toolbar-visible-p
específica de las versiones recientes de Emacs; el usocondition-case
se encarga de ambos requisitos. GNU Emacs proporciona una función dedicada, así que simplemente pruebo si esa función está disponible.Algunos nombres de caras cambian sobre las versiones. Use
facep
para probar la disponibilidad de un nombre de rostro.A veces es posible que desee cargar un paquete agradable si está presente, y no hacer nada si el paquete no está disponible.
require
tiene un argumento opcional para eso.Este argumento se introdujo en GNU Emacs 20.4 y no está disponible en XEmacs, por lo que si desea retroceder tanto, tendrá que envolverlo
condition-case
o usarloload
(que no verifica las bibliotecas ya cargadas) .Limite las dependencias de la versión a las características de nivel de usuario. No utilice las funciones de programación más nuevas que no están disponibles en todas las versiones que desea admitir: tendrá que proporcionar una versión de compatibilidad para versiones anteriores, y es más fácil mantener una versión única.
A veces necesita una función en muchos lugares, y está disponible en todas las implementaciones que le interesan, pero de una manera diferente. Este es principalmente el caso si desea admitir XEmacs y GNU Emacs: tenían una tendencia frustrante de copiar las características de los demás, pero no su interfaz. En este caso, definir una función de compatibilidad es más conveniente que probarlo en el punto de uso.
Por ejemplo, el siguiente código define una función que devuelve el sistema de ventanas del marco actual, la forma moderna de GNU, la forma moderna de XEmacs y la forma antigua cuando no se pueden combinar marcos de terminal y GUI en la misma instancia.
Dependencias del entorno
No hay mucho código que deba depender de la plataforma. La variable
system-type
indica el sistema operativo. Lo uso exclusivamente para activar algunos hacks params-dos
(sí, mis archivos son tan viejos) ywindows-nt
.Es posible que desee agregar directorios a su ruta de búsqueda ejecutable (
PATH
), pero eso suele hacerse mejor fuera de Emacs, en su.profile
sistema tipo Unix y a través del panel de control en Windows. Para probar si hay un programa externo disponible, llame alexecutable-find
.Para el código que necesita actuar de manera diferente dependiendo del tipo de GUI, si lo hay, verifique
window-type
o sus sucesores (ver arriba).Archivos de inicialización
Para obtener la máxima compatibilidad, ingrese su código
~/.emacs
. GNU Emacs comenzó a buscar en la~/emacs.d
versión 22. XEmacs comenzó a buscar~/.xemacs
en la versión 21.4. Un enfoque alternativo es colocar~/.emacs
y finalizar el código de compatibilidad cargando su archivo principal. Colóquelo en(setq load-home-init-file t)
algún lugar para evitar que las versiones recientes de XEmacs le pregunten si desea moverlo.emacs
a la ubicación exclusiva de XEmacs.Las diferentes versiones de Emacs pueden tener una expansión diferente e incompatible para algunas macros. Por lo tanto, no comparta sus archivos compilados por bytes entre versiones, compile los archivos en cada máquina.
A veces, una característica está en desuso, pero aún así desea usarla porque eso es todo lo que hay en alguna otra versión que desea admitir. Las advertencias del compilador de bytes provienen de la
byte-obsolete-variable
propiedad.Speaking Relativamente hablando, en comparación con XEmacs anteriores.
fuente
(Wiki de la comunidad. ¡Agregue el suyo!)
Si hay una función, agregada en una versión más nueva de Emacs, que le gustaría usar, verifique si está definida
fboundp
y defina una función de compatibilidad si no está definida.Se considera una mala idea dar a la función de compatibilidad el mismo nombre que la función real, ya que otro código de Elisp puede estar usando el mismo
fboundp
truco. Por lo tanto, use un prefijo para la función de compatibilidad y usedefalias
el mismo nombre si está definido. P.ej:Si alguna configuración solo se aplica a un determinado sistema operativo, hay algunas posibilidades diferentes. Puede comprobar la
system-type
variable, lo que vuelvegnu/linux
,darwin
,windows-nt
y algunas otras (véase la cadena de documentación).Es posible que tenga la tentación de usarlo
window-system
, aunque su cadena de documentación indica que "El uso de esta variable como booleano está en desuso", y recomienda usarlo en sudisplay-graphic-p
lugar. Tenga en cuenta que Emacs puede usar diferentes tipos de pantallas para diferentes marcos en la actualidad (por ejemplo, un marco en un terminal y otro en una ventana "adecuada"), por lo que esto puede causar sorpresas. Usecurrent-frame-configuration
oget-buffer-window-list
en su elisp para tomar la decisión correcta.Es posible que desee comprobar si se está ejecutando bajo el sabor correcto de emacs. Use featurep para verificar la variante. P.ej:
También puede usarlo para verificar que módulos específicos estén cargados. Por ejemplo, si solo usa un defun de common-lisp pequeño y fácil de definir, puede optar por definir en lugar de requerir. P.ej:
Evite almacenar archivos .elc. Estos no son compatibles con versiones anteriores o posteriores de algunas versiones de Emacs.
fuente
Si está utilizando funciones de
cl-lib
pero no desea utilizar versiones desaprovechadas sin espacios de nombres, haga que la biblioteca de compatibilidad cl-lib sea una dependencia de su proyecto. Eso le permitirá usar lascl-
funciones de espacio de nombres pero conservará la compatibilidad con versiones anteriores.fuente
cl-lib
todos modos? ¿Qué ventaja tiene sobre lacl
que existe desde hace al menos 20 años?cl
está en desuso y probablemente se eliminará eventualmente. Usarlo en código ha provocado advertencias de compilación de bytes durante bastante tiempo. Creo que la razón es que quieren reutilizar algunos de loscl
nombres (comodolist
) con diferentes semánticas.