2010-12-30 17 views
6

Estoy buscando escribir una plantilla de yasnippet que me permita agregar un encabezado de licencia a un búfer de script en Emacs. Un poco como this, pero un poco mejorada:comentarios de estilo de caja con yasnippet

  1. La cabecera necesita incluir datos por usuario, tales como el nombre de la fecha y de correo electrónico del titular del copyright, que se puede obtener con embedded elisp expansion de yasnippet.
  2. El encabezado debe comentarse con una sintaxis según el modo de programación en el que se encuentre el archivo actualmente. Ya existe a gist of a snippet that does all that. Básicamente equivale a incrustar (comment-region (point-min) (point)) al final de su fragmento.
  3. Ahora, Quiero cambiar el estilo de comentario a un cuadro. Consulte la documentación de emacs para la variable comment-style o, si desea ver cómo se ve un comentario de estilo de cuadro, simplemente llame al M-x comment-box en una región activa: Llama al comment-region con las opciones correctas.

Una primera aproximación de hacerlo es configurar el estilo modificando el final del fragmento anterior:

(let ((comment-style 'box)) 
      (comment-region (point-min) (point))) 

Por desgracia, la sangría se fastidien, y mi caja no es rectangular. Si comienzo del fragmento:

Copyright (c) ${1:`(nth 5 (decode-time))`} 
All rights reserved. 

Redistribution and use in source and binary forms, with or 
without modification, are permitted` 
     (let ((comment-style 'box)) 
      (comment-region (point-min) (point)))` 

La expansión de ese fragmento "rompe la caja" (estoy de depuración este fragmento con la sintaxis de comentario ocaml, no que debe importar):

(**************************************************************) 
(* Copyright (c) 2010         *) 
(* All rights reserved.          *) 
(*               *) 
(* Redistribution and use in source and binary forms, with or *) 
(* without modification, are permitted  *) 
(**************************************************************) 
  • Al principio pensé que la segunda línea estaba sangrada en función del tamaño del código incrustado de preexpansión, pero en ese caso, debería hacer que el final *) de esa línea venga 25 espacios demasiado pronto, no 4.
  • Si sangrado basado en no texto presente en el punto de inserción, el *) final debe llegar 4 espacios también tarde, no demasiado pronto.
  • Finalmente, no entiendo qué está pasando con la última línea, en la que hay sin expansión de código incrustado: Generalmente no tengo ningún problema para obtener un cuadro de comentario cuadrado de un párrafo con una última línea corta (ya sea usando comment-box, o la función elisp en el primero comentario de bloque de esta pregunta.

intenté hacer el comentario suceda después de la expansión fragmento, para evitar cualquier efecto secundario, añadiéndolo a yas/after-exit-snippet-hook, en sustitución de la última función del fragmento anterior con:

(add-hook 'yas/after-exit-snippet-hook 
     (let ((comment-style 'box)) 
      (comment-region (point-min) (point))) nil t) 

Pero eso no ayudó. Incluso si lo hiciera, me dejaría un gancho de expansión que comentaría todos los los fragmentos que quisiera usar en ese búfer, algo que ciertamente no quiero.

También debo añadir que he tratado de establecer yas/indent-line a fixed, añadiendo

# expand-env: ((yas/indent-line 'fixed)) 

al comienzo de mi fragmento, pero eso no cambia nada. ¿Alguna idea sobre cómo obtener una caja rectangular?


Editar: Tenemos a very nice answer, along with a proposed fix, (! Kudos & gracias, Seiji), sino una cuestión que queda sobre la forma de adaptarlo al caso en que uno quiere reutilizar un campo, digamos como la reutilización de $1 en :

Copyright (c) ${1:`(nth 5 (decode-time))`} 
All rights reserved. 

Redistribution and use in $1, in source and binary forms 
`(let ((comment-style 'box)) 
     (comment-region (point-min) (point-at-eol 0)))` 

En ese caso, las copias motor de la plantilla el valor (de longitud variable) obtenido para el campo $1, a saber 2011, a la última línea, en expansión plantilla (después de indentación), dando una línea de comentario 2 chara cters demasiado ancho. Resulta difícil predecir al escribir la plantilla que uno debe eliminar caracteres en esta línea. Quizás la reutilización de campo y la sangría correcta es demasiado pedir simultáneamente. ¿Alguien ve una manera de hacer esto, sin embargo?

Respuesta

5

Al cambiar su fragmento a este, se corrige la última línea.

Copyright (c) ${1:`(nth 5 (decode-time))`} 
All rights reserved. 

Redistribution and use in source and binary forms, with or 
without modification, are permitted 
`(let ((comment-style 'box))(comment-region (point-min) (point-at-eol 0)))` 

en cuenta que hay un salto de línea entre la licencia ("... están permitidos") y emacs lisp incrustados código.

En cuanto a la segunda línea, primero explicaré por qué ocurre esto y luego ofreceré una solución (fea). Cuando su fragmento se inserta en un archivo, los bloques incrustados de lisp se evalúan secuencialmente desde el principio del búfer hasta el final. Lo que esto significa en su fragmento es que (nth 5 (decode-time)) ha sido reemplazado por 2011 cuando se evalúa el siguiente bloque, (comment-region ...).

Como resultado, comment-region ve la segunda línea como

Copyright (c) ${1:2011} 

Así, comment-region pone suficientes espacios en blanco para esta cadena. Luego, el motor de plantillas transforma ${1:2011} en 2011, y esta transformación acorta la cadena en 5 caracteres. Esto explica la aparición prematura de *) por 5 caracteres en la segunda línea.

Una forma de solucionar esta situación es poner 5 espacios en blanco de vuelta después de comment-region se evalúa --- Algo a lo largo de la línea:

Copyright (c) ${1:`(nth 5 (decode-time))`} @ 
All rights reserved. 

Redistribution and use in source and binary forms, with or 
without modification, are permitted. 
`(let ((comment-style 'box))(comment-region (point-min) (point-at-eol 0)))`` 
(replace-string "@" "  " nil (point-min) (point))`$0 
+0

Gracias por la sugerencia 'point-at-eol', solucionó completamente el problema del Última línea. ** Gran ** explicación, gracias. Su solución funciona, pero es doloroso generalizar a muchos campos en una línea (donde tiene que contar manualmente el modelo para cada plantilla) e imposible de extender a * reutilizar * del campo $ 1 en otro lugar en la plantilla (donde lo haría tiene que ** eliminar ** tantos espacios en blanco como se cree la evaluación del lisp incrustado). Voy a esperar un momento, y si nadie viene con una solución para eso, voy a "aceptar" tu respuesta. – huitseeker

+1

Acepto que mi solución para la segunda línea no es óptima. Sería genial si 'yas/after-exit-snipeet-hook' funciona en el texto que vemos. Sin embargo, parece que el gancho funciona en el texto subyacente (por ejemplo, '$ {1: ...}'). Por cierto, si configura el gancho en '# expand-env', el gancho solo afecta al fragmento y no a otros fragmentos --- al agregar' # expand-env: ((yas/after-exit-snippet-hook list (let ((comment-style 'box)) (comment-region (point-min) (point-max) nil))))) ' –

1

Esto podría ser de alguna utilidad para usted:

# -*- mode: snippet -*- 
# name: param 
# key: param 
# -- 
m.parameter :${1:arg},${1:$(make-string (- 14 (string-width text)) ?\ 
         )}:${2:type}$> 

Utiliza un espejo con una función para crear el espacio en blanco de posicionamiento. Por lo tanto, para usted, esto podría significar algo como esto:

(* Copyright (c) ${1:2011}${1:$(make-string (- 72 (string-width text)) ?\)} *) 
(* ${2}${2:$(make-string (- 72 (string-width text)))}*) 

Otra opción podría ser usar yas/after-exit-snippet-hook, pero que parece estar en desuso.(Ah, y quise filtrar el texto usted mismo, la región de comentarios que ya probó es más inteligente. Pruebe indent-region?)

+0

Esto es inteligente, pero desafortunadamente, como se explica en [la respuesta de Seiji] (http : //stackoverflow.com/questions/4563788/box-style-comments-with-yasnippet/4583535#4583535), el motor de plantillas reemplazará los campos * después de * la ejecución de bloques, lo que significa que el espacio en blanco insertado por '(make-string ...) 'es dos veces 5 caracteres cortos (para' $ {1:} $ {1:} '). (gracias por la sugerencia de gancho, pero ya mencioné mis intentos fallidos en la pregunta original) – huitseeker

Cuestiones relacionadas