1 puntos por GN⁺ 1 시간 전 | 1 comentarios | Compartir por WhatsApp
  • zig fmt puede usarse como un formateador orientable que refleja la forma sintáctica ya presente en el archivo y puede acomodar el mismo código en varios layouts
  • En las llamadas a funciones, la presencia o ausencia de trailing comma cambia el resultado: sin coma se une en una sola línea, y con coma los argumentos se colocan uno por línea
  • El flujo real consiste en decidir primero la disposición de código deseada, agregar unas cuantas comas y luego presionar el atajo de formateo para que zig fmt se encargue del resto
  • En los arreglos, además del trailing comma, también se refleja la posición del primer salto de línea; si el primer salto va después del tercer elemento, se alinean en grupos de 3 elementos
  • Si se usa ++ con cuidado para concatenar arreglos, se puede variar la cantidad de elementos por línea y, al pasar pares --key y value a un subprocess, se pueden concatenar un arreglo de argumentos fijos y otro de pares de opciones para alinearlos

Cómo orientar zig fmt

  • zig fmt puede usarse como un formateador orientable porque observa la forma sintáctica ya presente en el archivo y puede acomodar la misma sintaxis de varias maneras
  • En las llamadas a funciones, la presencia o ausencia de trailing comma cambia el layout
    f(1, 2,
          3);
    
    // -> zig fmt ->
    
        f(1, 2, 3);
    
    f(1, 2,
          3,);
    
    // -> zig fmt ->
    
        f(
            1,
            2,
            3,
        );
    
  • En el uso real, el flujo consiste en decidir primero la disposición de código deseada, agregar unas cuantas , y luego presionar el atajo de formateo para que zig fmt se encargue del resto
  • En lugar de hacer que el formateador adivine el layout, puede funcionar mejor dejar que el usuario conserve directamente las decisiones clave
  • La conclusión es que el 90% del buen formateo depende de las líneas en blanco entre bloques lógicos y de elegir variables intermedias adecuadas, así que es mejor aprovechar esas decisiones que eliminarlas

Layout de alineación por columnas en arreglos

  • En los arreglos, zig fmt no solo usa el trailing comma para poner un elemento por línea, sino que también refleja la posición del primer salto de línea
    .{ 1, 2, 3,
          4, 5, 6, 7, 8, 9, 10, 11,  };
    
  • Si el primer salto de línea va después del tercer elemento, el resultado también se alinea en grupos de 3 elementos
    .{
            1,  2,  3,
            4,  5,  6,
            7,  8,  9,
            10, 11,
        };
    
  • Si se usa con cuidado la concatenación de arreglos con ++, se puede variar la cantidad de elementos por línea
  • Al pasar pares --key y value a un subprocess, se puede concatenar un arreglo de argumentos fijos y otro de pares de opciones para alinearlos así
    try run(&(.{ "aws", "s3", "sync", path, url } ++ .{
        "--include",            "*.html",
        "--include",            "*.xml",
        "--metadata-directive", "REPLACE",
        "--cache-control",      "max-age=0",
    }));
    

1 comentarios

 
GN⁺ 1 시간 전
Opiniones en Lobste.rs
  • Recuerdo que gofmt también tenía un comportamiento de formato guiado parecido, y ese tipo de formateador me gusta más que rustfmt
    Aun así, me parece mejor tener algún tipo de automatización de formato que no tener formateador en absoluto

    • La frase “cualquier cosa es mejor que no tener formateador” no me resulta fácil de dejar pasar
      Los autoformateadores fuerzan la mediocridad: levantan a quienes no saben formatear, pero también bajan a quienes sí saben hacerlo bien
      Los usaría al colaborar, si es difícil confiar en lo que otras personas quieren o en sus reglas personales de estilo, pero trabajando solo no los usaría jamás
      Yo tengo mis gustos y el formateador tiene los suyos, y son irreconciliablemente distintos
      Dicho eso, lo que muestra este artículo en sí es impresionante
      Esa frase me recuerda la línea de Yente, la casamentera de Fiddler on the Roof: “¡Hasta un mal marido—que Dios nos libre—es mejor que no tener marido!”
    • Si mal no recuerdo, el formateador de Elm también funcionaba de forma parecida, y me parecía bastante bueno en comparación con los formateadores que no tienen en cuenta el formato original
    • Uso clang-format en algunos proyectos de C++ y es terrible
      La estabilidad entre versiones es demasiado baja, así que actualizar clang-format termina en un commit de formato que toca todas las líneas del código
      De verdad no estoy seguro de que sea mejor que no tener formateador
    • Durante mucho tiempo pensé que “cualquier formateador es mejor que no tener uno”, pero últimamente cambié de opinión por completo
      Los autoformateadores resuelven sobre todo un problema humano: eliminar las discusiones de detalle irrelevante en los pull requests
      Pero ahora que estamos pasando al desarrollo con agentes, ese problema cada vez importa menos
      En varios proyectos las máquinas ya están haciendo la mayor parte del trabajo, y en ese contexto me da la impresión de que es mejor no correr el formateador
  • Cuando construyo argumentos de línea de comandos en Python, me gusta desplegar tuplas dentro de una lista, así que el ejemplo final del artículo probablemente lo escribiría así

    [  
      "aws",  
      "s3",  
      "sync",  
      path,  
      url,  
            *("--include", "*.html"),  
      *("--include", "*.xml"),  
      *("--metadata-directive", "REPLACE"),  
      *("--cache-control", "max-age=0"),  
    ]  
    
  • La última vez que revisé, zig fmt no tenía forma de configurar un límite de 80 columnas en lugar de 100; ¿sigue siendo así?
    Si trabajo varias horas al día, me cansa menos la vista usar un tamaño de fuente más grande en la terminal, y la diferencia entre 80 y 100 columnas decide si puedo tener dos divisiones de vim y nerd tree una al lado de la otra

    • zig fmt no tiene límite de columnas
  • Como alguien que introdujo rigid formatter en un equipo que antes no tenía ningún formateador, a veces extraño poder influir manualmente en el formato
    En ese sentido, está muy bueno que Zig sea flexible

  • ¡Excelente!
    ¿Habrá algún formateador de TS/JS que funcione así?
    Tengo un proyecto que usa maplibre-gl, y a veces las expresiones de la especificación de estilos quedan tan exageradamente formateadas que no se entiende nada
    Por ahora dejé de usar formateador, pero entre depurar, copiar y comentar código, todo se va ensuciando
    Quizás hasta se podría hacer que el formateador de Zig también formatee otros lenguajes :)

    • Prettier tiene algo parecido, pero específicamente limitado a literales de objeto, y solo permite elegir entre “todo en una sola línea” y “cada elemento en una línea distinta”
      Por ejemplo, no hay manera de indicarle al formateador que ponga cuatro elementos por línea
      Además, si un literal de objeto se vuelve demasiado largo, Prettier termina forzándolo al formato de “cada elemento en una línea distinta”, sin importar cómo venga el texto de entrada
  • Me han decepcionado los formateadores livianos, básicamente formateadores que solo insertan saltos de línea, así que me gusta y me da cierta envidia la idea de tener esta flexibilidad dentro de un ejemplo más estricto :p
    Hace poco, respondiendo en el fediverso a una pregunta sobre escribir y formatear Lisp con fuentes proporcionales, mencioné variantes de s-expressions con espacios significativos como wisp, Readable/Sweet expressions y SRFI 119 y 110
    También señalé que esa familia de sintaxis devuelve parte del control sobre los saltos de línea al aprovechar extensiones opcionales de notación infija

  • Es un diseño interesante, pero no estoy seguro de que me guste
    En mi formateador lo manejo distinto: el formateador ignora las comas finales al decidir el formato; luego, si algo queda dividido en varias líneas, siempre agrega una coma final, y si queda en una sola línea, siempre la elimina
    Así que no permite “guiarlo”, pero f(1, 2, 3) se formatea de manera consistente sin importar si tenía o no coma final, ni la cantidad o tipo de espacios entre tokens
    Hace falta cierto grado de guía
    Por ejemplo, si tienes un literal de lista largo como [<expr1>, <expr2>, ..., <expr100>], la mayoría de los formateadores pondrán cada expresión en su propia línea, pero puede que quieras meter tantas como sea posible en cada línea
    Me parece raro decidir eso a partir de una coma final, y en general las opciones pueden ser N, no solo 2
    Creo que para esto encajan mejor los atributos
    Por ejemplo, quizá ya exista, pero se podría poner algo como #[rustfmt::list_layout(flow)] delante de una sentencia para influir en el formato de los literales de lista dentro de esa sentencia
    Si hay demasiada “guía”, se perjudica el propósito del formateador de volver consistente el formato del código en todo el ecosistema y facilitar la revisión de código, así que debería limitarse a casos puntuales
    Los literales de lista largos me parecen un caso realmente válido
    También tengo un ejemplo en mi proyecto donde el formato ayuda a revisar valores esperados en tests, que es este
    También se me ocurre otro comportamiento de “guía” en el formateador de Dart: en literales de lista largos puedes agregar líneas de comentarios para agrupar líneas
    Por ejemplo, si tienes [1, 2, 3, ..., 1000], pondrá cada elemento en una línea, pero puedes agruparlos manualmente así

    [1, 2, 3, 4, 5,  //  
     6, 7, 8, 9, 10, //  
     ...]  
    

    No sé si eso fue una función puesta a propósito o un efecto secundario de cómo maneja los comentarios

    • Ese es exactamente el comportamiento de rustfmt, y me vuelve loco
      A veces, incluso si se supera el límite de longitud de línea, es más legible no partir una llamada de función, y me gustaría poder reflejar mi criterio ahí
      Un caso que se me viene a la cabeza es OpenGL
      Normalmente modificas o usas un mismo recurso, y por ejemplo al inicializar texturas terminas con muchas llamadas seguidas a gl.*, pero rustfmt las parte sin ningún criterio más allá del objetivo robótico de “la línea es demasiado larga; hay que cortarla”
      Este ejemplo es artificial para mostrar el comportamiento y no coincide por completo con el comportamiento real de rustfmt
      Tampoco las líneas son tan largas
      Ahora mismo estoy escribiendo desde el teléfono, así que no tengo herramientas para hacer un ejemplo 100% exacto
      gl.bind_texture(gl::TEXTURE_2D, tex);  
      gl.tex_parameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST);  
      gl.tex_parameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);
      
      // -->
      
      gl.bind_texture(gl::TEXTURE_2D, tex);  
      gl.tex_parameteri(  
          gl::TEXTURE_2D,  
          gl::TEXTURE_MIN_FILTER,  
          gl::NEAREST,  
      );  
      gl.tex_parameteri(  
          gl::TEXTURE_2D,  
          gl::TEXTURE_MAG_FILTER,  
          gl::NEAREST,  
      );  
      
      Dividir en varias líneas una secuencia de llamadas gl.tex_parameteri como esa en realidad es peor que dejar cada llamada completa en una sola línea
      Si las columnas están alineadas, es mucho más fácil ver la diferencia entre ambas líneas
      La versión partida pierde proximidad visual y es más difícil de leer
      Ya no puedes comparar fácilmente ambas líneas de un vistazo
      También pasa la ridiculez de que falla por completo cuando no puede formatear algo para que entre dentro del límite de caracteres
      Esto me pasa seguido escribiendo código de compilador, cuando construyo mensajes de diagnóstico como literales de cadena, porque esos mensajes pueden ser bastante largos
      rustfmt no sabe cómo dividirlo, así que se rinde y deja sin formatear toda la sentencia
      Suele verse algo así
      match something {  
          // ... match arms above this one ...  
          _ => emit_diagnostic(&mut state, "This is a very long message to try and illustrate the problem. Help: please consult a doctor.")  
      }  
      
      El hecho de que emit_diagnostic sea solo una expresión hace que renuncie a formatear todo el match, y eso es simplemente tonto
      Todo eso se habría evitado si no tratara de forzar mi código a un máximo de 100 columnas
  • Para quien, como yo, tuvo que buscarlo al ver el comentario del final: ++ es el operador de concatenación de arreglos
    Así que puedes dividir un arreglo en dos para que se formatee de forma distinta