Julia: ¿Qué se necesita para incluir ClearStacktrace.jl en Base?

Creado en 25 may. 2020  ·  99Comentarios  ·  Fuente: JuliaLang/julia

El título lo dice todo. Creo que descubrí un buen formato para presentar los rastros de pila, y creo que todos los usuarios podrían beneficiarse de él. Actualmente está en ClearStacktrace.jl y depende de Crayons.jl para los colores.

Quiero saber qué puedo hacer para que este PR esté listo. No sé cómo Julia Base maneja los colores REPL, cuáles puedo usar, cómo accedo a ellos sin Crayons etc. Tampoco sé si puede haber complejidades de pila específicas del sistema. rastros que he pasado por alto, probando esto solo en una máquina Windows y Mac.

La idea básica es tener tres columnas, función, módulo y firma. Básicamente, la función y el módulo juntos deberían encajar siempre en un REPL horizontalmente, mientras que las firmas pueden ser muy largas y, por lo tanto, pueden desbordarse en nuevas líneas, mientras permanecen intactas al cambiar el tamaño del REPL (en comparación con el diseño de tabla más complejo pero frágil). Las rutas de código obtienen una nueva línea cada una, y también pueden desbordarse si son demasiado largas. Esto mantiene intactos los enlaces en los que se puede hacer clic en Atom / VSCode y similares.

Solo como referencia, aquí está la comparación antes y después del README:
Antes:
grafik
Después:
grafik

Comentario más útil

otra iteración: traté de obtener nombres de variables allí, a pesar de que todo se siente súper hack para mí, ya que no estoy muy familiarizado con todos los aspectos internos. Cambié el color de los módulos porque parecía obtener una respuesta positiva en general, aunque es discutible cómo se deben asignar los colores. Pero con los colores, siento que el módulo de una entrada choca un poco con el nombre de la función de la siguiente. Así que introduje saltos de línea. Hace que todo sea más largo, por supuesto, pero me gusta el espacio adicional para respirar y la claridad.

grafik

Todos 99 comentarios

Sería muy bueno tener esto. O al menos tal vez una versión recortada que mejora la impresión de trazos de pila de forma predeterminada en Base.

Estoy todo a favor. Lo principal que no entiendo son los colores de las firmas. ¿Parecen ... aleatorios? Supongo que los diferentes colores están ahí para facilitar la selección de diferentes elementos, pero es un poco extraño. ¿Qué tal el color == profundidad de anidación? Creo que la principal rareza está en, por ejemplo, Tuple{Symbol,Symbol} donde los dos Symbol s son de diferentes colores.

Hay otra cosa que realmente me gustaría ver:

julia> foo(x::T, y::T) where T = error("whoops")
foo (generic function with 1 method)

julia> function bar()
           a = rand(3, 5)
           b = view(a, :, 2:3)
           c = reinterpret(Float32, b)
           foo(c, c)
       end
bar (generic function with 1 method)

julia> bar()
ERROR: whoops
Stacktrace:
 [1] error(::String) at ./error.jl:33
 [2] foo(::Base.ReinterpretArray{Float32,2,Float64,SubArray{Float64,2,Array{Float64,2},Tuple{Base.Slice{Base.OneTo{Int64}},UnitRange{Int64}},true}}, ::Base.ReinterpretArray{Float32,2,Float64,SubArray{Float64,2,Array{Float64,2},Tuple{Base.Slice{Base.OneTo{Int64}},UnitRange{Int64}},true}}) at ./REPL[1]:1
 [3] bar() at ./REPL[2]:5
 [4] top-level scope at REPL[3]:1

pero desde

julia> m = first(methods(foo))
foo(x::T, y::T) where T in Main at REPL[1]:1

julia> m.sig
Tuple{typeof(foo),T,T} where T

parece que deberíamos poder imprimir la entrada 2 como algo como

[2] foo(::T, ::T) where T = Base.ReinterpretArray{Float32,2,Float64,SubArray{Float64,2,Array{Float64,2},Tuple{Base.Slice{Base.OneTo{Int64}},UnitRange{Int64}},true}}

Un pequeño comentario, pero para mí actualmente es quizás demasiado color "ensalada". El contador de fotogramas de pila es azul, todos los colores diferentes en la firma, etc. Para los colores Base hasta ahora, solo hemos usado los 16 colores del sistema (8 + 8 brillantes) y eso hace que la coloración elegante sea un poco más difícil.

Buenas sugerencias en general. Tal vez un par de comentarios por qué hice las elecciones de color hasta ahora:

Los números son azules porque son importantes, por lo que no deberían estar en gris, pero hacerlos blancos me pareció como si estuvieran luchando por llamar la atención con los nombres de las funciones.

Los módulos usan los colores primarios en un ciclo, creo que esto es muy útil porque permite filtrar rápidamente la traza de los módulos relevantes. Esto es algo que tiene mucho que ver con el formato de seguimiento de pila actual. La idea es que las personas deberían verse obligadas a leer lo menos posible para encontrar lo que buscan. (Hasta ahora he realizado principalmente investigaciones sobre el movimiento de los ojos y la atención en mi vida académica, por lo que esos aspectos son importantes para mí;))

Los colores de las firmas son muy discutibles. Los de la captura de pantalla de arriba fueron elegidos para ser solo ligeramente diferentes del gris oscuro. Al mismo tiempo, quería que los diferentes componentes semánticos fueran discriminables. Es por eso que todos los tipos y parámetros de tipo (llaves y comas) provocan un cambio de color. Hay tres colores, lo que significa que no habrá dos vecinos con el mismo color. Descubrí que es bastante difícil distinguir palabras sueltas en firmas de tipografía grandes si todas son solo en blanco. Los tonos ligeramente diferentes ayudan mucho pero también hacen que todo sea un poco más ruidoso visualmente.

Como el conjunto de 16 colores no tiene colores que sean solo marginalmente diferentes del gris oscuro, probablemente no sea algo que pueda incluirse en Base. En una actualización reciente, reemplacé los colores con tres tonos de gris ligeramente diferentes del conjunto ANSI, pero supongo que incluso eso no será compatible en todas partes.

Oh, también el color del marco de la pila y los colores del módulo, así como el gris oscuro y el blanco, son todos colores del sistema. Es solo mi tema particular de VSCode el que los muestra como se ve aquí.

Sería genial tener esto.

Al escanear tipos de argumentos, a menudo es bastante difícil averiguar dónde se detiene uno y comienza el siguiente. Colorear el nivel superior de manera diferente puede ser muy útil aquí, y tal vez incluso numerar los argumentos:

 [3] (_1 :: DataFrames.var "# fun ## 309 #" { ... lighter ... }, _2 :: NamedTuple { ... lighter ... }, _3 :: Int64})

Deberíamos poder mostrar los nombres de los argumentos, como hacemos en la impresión de methods(f) .

¿cómo es esto? Reemplacé los colores de la firma con gris oscuro, pero :: es blanco, por lo que es sobresaliente donde comienzan los tipos de argumentos. especialmente útil con el tipo de monstruo en la posición 11
grafik

Me gusta. Será aún mejor con los nombres de los argumentos.

Es una lástima que el orden "función - módulo - argumentos" funcione tan bien para el diseño, pero en realidad no tiene sentido semánticamente. Aunque no tengo una solución; claramente, es mejor que la función sea lo primero. ¿Quizás el módulo podría ir a la siguiente línea antes de la ubicación del archivo? Después de todo, es parte de la ubicación. Entonces quizás tampoco necesitemos el encabezado.

Creo que también podríamos poner los números en texto normal y los nombres de las funciones en negrita y / o blanco.

¿Podría el nombre de archivo al final de la ruta de código (y posiblemente el número de línea) tener su propio color más claro también?

¿Quizás el módulo podría ir a la siguiente línea antes de la ubicación del archivo? Después de todo, es parte de la ubicación. Entonces quizás tampoco necesitemos el encabezado.

Probaré un par de cosas con estas sugerencias.

¿Podría el nombre de archivo al final de la ruta de código (y posiblemente el número de línea) tener su propio color más claro también?

Técnicamente puede, por supuesto;) Siempre es un compromiso entre una mejor visibilidad y un ruido que llama la atención.

¿Por qué no escribir los módulos primero, ya que forman parte del nombre completo de la función? Quizás con el color sea lo suficientemente claro como para escribir Core.eval , etc., o aún podrían estar alineados como columnas. (O tal vez intentaste esto y se veía horrible).

Pensamiento realmente loco: si imprimir los tipos de argumentos ocuparía más de una línea, imprima la firma en forma doblada y luego use REPL.TerminalMenus para permitir que los espectadores la expandan. Algo como:

julia> run_command(args...)
    Function    Arguments              Location
[1] f           (x::Int, y::Float64)   MyModule1, /path/to/file1.jl: 15
[2] g          +(...)                  MyModule2, /path/to/file2.jl: 64
...

julia> lasttrace()
# presents the above in menu form, allowing user to expand line 2

Relacionado: # 35915 (que planeo usar para crear un menú de árbol plegado, https://github.com/JuliaCollections/FoldingTrees.jl).

¿Cómo se ve con la ruta de código reorganizada en este orden: LineNumber Filename Path
Entonces sus ojos tienen una ubicación estable para buscar el número de línea y el nombre de archivo sin necesidad de color adicional para ellos (parece que siempre estoy buscando el nombre de archivo y el número de línea enterrados en los detalles, ¿puede decirlo?)
Y para el trabajo de REPL interactivo, me encanta la idea doblada de arriba :)

¿Por qué no escribir los módulos primero, ya que son parte del nombre completo de la función?

Sí, me gusta la idea, creo que empecé sin color y eso no funcionó tan bien, pero así es bastante legible. Lo intentaré sin columnas a continuación, aunque las columnas siempre son agradables porque guían tus ojos.

grafik

No estoy seguro de eso; el nombre de la función es una pieza de información mucho más importante que el módulo. Para mí, al menos, la información más importante es definitivamente el nombre de la función, el nombre del archivo y el número de línea. Además, para los scripts, la columna de la izquierda sería un montón de Main o en blanco, lo que no es ideal para ese caso de uso.

Creo que cuando leo stacktraces, principalmente busco la última llamada en mi código antes de que vaya al código Base / paquete, ya que generalmente el error está en mi código. Entonces, en ese caso, el módulo es bastante importante y la llamada a la función no es lo que estoy escaneando primero.

Qué tal esto:

[1]  get_ticklabels   ::AbstractPlotting.Automatic, ::Int64
     in MakieLayout at ~/.julia/packages/MakieLayout/COfBu/src/lineaxis.jl:372

Los nombres de los módulos seguirían alineados para que fueran fáciles de escanear.

De hecho, acababa de probar algo parecido a eso. Esta vez coloreé los nombres de las funciones, por lo que siguen siendo los más destacados, pero llevan la información del módulo en su color. Entonces, todavía hay una agrupación obvia, pero con menos enfoque en todos los nombres de los módulos.

grafik

La primera vez que vi que probablemente me volvería loco tratando de averiguar qué significaban los colores: alegría: si va a haber colores por módulo, parece mejor simplemente aplicar el color al nombre del módulo.

Me gustan los nombres de los módulos, se pierden un poco en esta última imagen.

Si están en la parte inferior, ¿quizás hacerlos del mismo color brillante conectaría las cosas? (Y aclare dónde cruza el límite de un módulo). Y, tal vez, si el nombre del módulo aparece en la ruta, simplemente podría resaltarse allí, eso también movería el nombre colorido del borde izquierdo donde están las funciones.

Para inspirarme, publico algunas imágenes de la última vez que surgió el ajuste del formato de seguimiento de pila.

bild

bild

A menudo, el paquete exacto no es tan interesante como la naturaleza del código: ¿es el núcleo de julia, una biblioteca que estoy usando, la biblioteca que estoy desarrollando o un script? Podríamos tener cuatro colores: core / base / dev / stdlib, paquetes, paquetes actualmente ]dev ed y todos los demás (incluido el script / REPL). Algunas de estas distinciones son bastante arbitrarias y la clasificación es un poco frágil, pero colorear el método basado en esto maximizaría (al menos para mí) la información sin mostrar ningún texto adicional y manteniendo un conjunto de colores pequeño y fácil de memorizar.

Para mí, los colores son más sobre cambios de límites, donde el código de un módulo comienza y el otro termina. Es por eso que probablemente no les asignaría un significado inherente. Por otro lado, eso puede resultar confuso.

Intenté simplificar más y eliminé las columnas nuevamente porque sin la columna del módulo ya no son tan útiles. Luego, primero coloreé solo el número de línea por módulos, pero esto aún dejaba el nombre del archivo no tan visible, lo que muchos comentarios dijeron que es importante. Así que también coloreé eso en el color del módulo. El nombre del módulo en sí no está coloreado porque está demasiado cerca del nombre de la función y es demasiado ruidoso.

Aquí está la versión con números y nombres de archivo coloreados:

grafik

aquí sin nombres de archivo coloreados

grafik

¿También puedes intentar colorear la ruta completa del archivo?

Algunas ideas...
Nombre de archivo y número de línea en una ubicación coherente con espacios dobles para resaltarlos.
El color del nivel de pila y el color del módulo coinciden entre sí para emparejar visualmente las líneas relacionadas.
Nombre de archivo, número de línea y ruta en un tono ligeramente diferente que los tipos de parámetros para distinguir sin desorden.
stacktrace
[Los colores en este ejemplo son arbitrarios, más pensando en cómo se relacionan sus posiciones.
Los niveles de pila que faltan en el ejemplo y la lista de tipos de parámetros abreviada en el último elemento se deben a que escribí el ejemplo a mano.]

Código utilizado para producir la muestra anterior en caso de que alguien quiera jugar con ella:

function main()

    errors = [
              ("1", "get_ticklabels", ("AbstractPlotting.Automatic", "Int64"), "372", "lineaxis.jl", "MakieLayout", "~/.julia/packages/MakieLayout/COfBu/src")
              ("2", "get_ticklabels", ("AbstractPlotting.Automatic", "Int64"), "351", "lineaxis.jl", "MakieLayout", "~/.julia/packages/MakieLayout/COfBu/src")
              ("3", "#105", ("AbstractPlotting.Automatic",), "152", "lineaxis.jl", "MakieLayout", "~/.julia/packages/MakieLayout/COfBu/src")
              ("8", "OnUpdate", ("Tuple{Float32,Float32}",), "218", "Observables.jl", "Observables", "~/.julia/packages/Observables/0wrF6/src")
              ("9", "#setindex!#5", ("Observables.var\"#6#8\"",), "138", "Observables.jl", "Observables", "~/.julia/packages/Observables/0wrF6/src")
              ("10", "setindex!", ("Observables.Observable{Any}",), "126", "Observables.jl", "Observables", "~/.julia/packages/Observables/0wrF6/src")
              ("11", "#LineAxis#95", ("Base.Iterators.Pairs{Symbol,Observables.Observable,NTuple{28,Symbol},NamedTuple{(:endpoints, :limits, :flipped, :ticklabelrotation, :ticklabelalign, :lables
ize, :labelpadding, :ticklabelpad, :labelvisible, :label, :labelfont, :ticklabelfont, :ticklabelcolor}",), "270", "lineaxis.jl", "MakieLayout", "~/.julia/packages/MakieLayout/COfBu/src/lobjects")
    ]

    println()
    for (idx, err) in enumerate(errors)
        # Module color
        mc = idx <= 3 ? :light_red : (idx >= 7 ? :light_red : :light_yellow)
        # Path color
        pc = :blue
        printstyled("[", color=mc)
        printstyled("$(err[1])", color=mc)     # errorno
        printstyled("]  ", color=mc)
        printstyled("$(err[5])", color=pc)     # filename
        printstyled(":", color=pc)             # colon
        printstyled("$(err[4])", color=pc)     # lineno
        printstyled("  $(err[7])", color=pc)   # path
        println()
        printstyled("$(err[6]) ", color=mc)    # module
        printstyled("$(err[2]) ", color=:bold) # function
        printstyled("(", color=:light_blue)    # param types
        for t in err[3]
            printstyled("::", color=:white)
            printstyled("$t", color=:light_blue)
        end
        printstyled(")", color=:light_blue)
        println()
    end
end

El problema con esto es que esto no deja los enlaces en los que se puede hacer clic en Atom / VSCode, etc. Esto es algo que uso muy a menudo y creo que otros también lo hacen. De hecho, incluso amplío explícitamente las rutas base para que se pueda hacer clic en ellas. Esto, por supuesto, imprime más. Pero creo que aumenta la utilidad. Sé que hay alguna forma de saltar para apilar las entradas de seguimiento por número en el REPL con algún atajo, pero en mi opinión, esto es mucho menos intuitivo que simplemente hacer clic en un enlace.

Podría tener sentido aprovechar la oportunidad para unificar la forma en que se imprime la información de línea con el sistema de registro, por ejemplo:

bild

Además, tenga en cuenta que el sistema de registro contrata el homedir

julia> include("foo.jl")
┌ Warning: foo
└ @ Main ~/julia/foo.jl:1

Creo que aquí hay dos ideas centrales en la propuesta:

  • Tenga la información de la línea en una línea separada de la firma (y quizás delimítela con algún color para que sea más fácil de encontrar).
  • Muestre el módulo.

Así que aquí hay un intento un poco más conservador con ambas ideas:

bild

Una versión con nombres de variables agregados y color solo en los nombres de los módulos (pero que por lo demás coinciden con la forma en que @info imprime las rutas):

Screenshot 2020-05-28 at 15 55 56

Este no tiene firmas de tipo muy largas, pero quizás tener nombres de variables como este (¿si eso es posible?) Hará que sea más fácil detectar el tipo más externo de cada argumento.

Si hay tres niveles de neutral disponibles (como negrita / normal / gris), entonces imprimir la ruta del archivo de manera más ligera que la firma parece (IMO) como una buena manera de evitar que las cosas funcionen juntas. (Esto también es lo que hace @info .)

Adaptando el código de @timotaularson

 dejar
 printstyled ("\ njulia>", color =: verde)
 println ("f ()")
 printstyled ("" "ERROR: DimensionMismatch (" A tiene dimensiones (1,2) pero B tiene dimensiones (3,4) ")" "", color =: light_red)
 println ("\ nStacktrace:")
 para (idx, err) en enumerar (errores)
 mc = idx <= 3? : azul: (idx> = 7?: azul:: amarillo) # Color del módulo
 printstyled ("[$ (err [1])]", color =: normal, bold = true) # errorno
 printstyled (err [2], color =: normal, bold = true) # función
 printstyled ("(", color =: normal) # tipos de parámetros
 para (i, t) en enumerar (err [3])
 i! = 1 && printstyled (",", color =: normal)
 printstyled (rand ('a': 'z') ^ 2, color =: light_black)
 printstyled ("::", color =: normal)
 printstyled ("$ t", color =: normal)
 fin
 printstyled (")", color =: normal)
 println ()
 printstyled ("@", color =: light_black)
 printstyled (err [6], color = mc) # módulo
 printstyled ("$ (err [7]) / $ (err [5]): $ (err [4])", color =: light_black) # ruta
 println ()
 fin
 fin

Creo que aquí hay dos ideas centrales en la propuesta:

* Have the line info on a separate line from the signature (and perhaps delimited it with some color to make it easier to find).

* Show the module.

Así que aquí hay un intento un poco más conservador con ambas ideas:

Me gusta esto. Creo que el término es "mata a tus queridos", y mi amor podría ser el color. Pero puedo ver cómo algo atenuado podría ser más adecuado para algo tan básico. Lo cambié un poco para que el nombre del módulo y el nombre de la función se alineen, lo que crea una línea de contraste vertical casi como una columna. Eso debería ayudar a encontrar la información relevante. Aunque todavía creo que no pondría los tipos en blanco, porque se ensucian mucho. Si tuviéramos nombres de variables, tal vez los de blanco se verían bien.

grafik

Me gusta esto. Creo que el término es "mata a tus queridos", y mi amor podría ser el color.

Solo para que sepas que conozco tu situación, https://github.com/JuliaLang/julia/pull/18228. Este es un tema que es muy divertido para montar en bicicleta y todos tienen un cubo de pintura, je. Como puede ver, las relaciones públicas también comenzaron de manera bastante ambiciosa, pero poco a poco se volvieron más y más conservadoras, je.

Para mí, la última propuesta es definitivamente una mejora con respecto al statu quo. Dos cosas estoy pensando:

  • Si es posible, sería bueno tener algún tipo de "gancho" para sus ojos para la información de la línea porque tiende a mezclarse con la firma cuando la firma es larga.
  • Probablemente deberíamos alinear los números de stackframe cuando hay más de 10 de ellos:
    [ 8] [ 9] [10] [11]
    etc. Eso haría que el @ también se alineara.

Me gusta, creo que estamos llegando a alguna parte. Ser prudente con los colores siempre es bueno, ya que eso expone menos área de superficie para el desprendimiento de bicicletas, además de disminuir el riesgo de que un color sea ilegible en el terminal de alguien.

Espaciar las cosas es bueno, pero desafortunadamente la sintaxis f (...) está explícitamente prohibida, por lo que creo que debemos eliminar el espacio o eliminar los paréntesis.

La muestra más reciente generalmente se ve bien, pero apoyo la idea:

Si es posible, sería bueno tener algún tipo de "gancho" para sus ojos para la información de la línea porque tiende a mezclarse con la firma cuando la firma es larga.

Y espero que el anzuelo sea de otro color o (preferiblemente) de brillo.

Tal vez podría hacer el ciclo de colores para los módulos, pero solo aplicarlo a [] a cada lado del número de nivel de pila, por lo que si no puede ver los colores por alguna razón, no se pierde mucho.

Quizás podrías hacer el ciclo de colores para los módulos pero solo aplicarlo a []

Es difícil incluso ver el color correctamente si son solo corchetes y están en un área de contraste, por lo que no creo que eso funcione demasiado bien ...

la sintaxis f (...) está explícitamente prohibida

Creo que funciona bien incluso sin el espacio, debido a la diferencia de contraste.

Si es posible, sería bueno tener algún tipo de "gancho" para sus ojos para la información de la línea

Estoy de acuerdo, creo que funciona bien dejar los números de línea en gris pero en negrita, eso los hace un poco sobresalientes si los busca, pero el siguiente paso para hacerlos blancos es demasiado ruidoso en mi opinión.

Probablemente deberíamos alinear los números de stackframe

Lo intenté con espacios dentro de los corchetes como en su ejemplo, pero descubrí que se veía un poco extraño, así que ahora estoy alineando los números entre corchetes. Creo que funciona bastante bien.

Aquí está la versión más reciente con todas esas ideas incorporadas:

grafik

Y como beneficio adicional, así es como podría verse con nombres de variables (aleatorios). Nuevamente, solo estoy usando gris negrita porque todos estos nombres de variables no deberían luchar por su atención, pero deberían ser un poco discernibles si los busca.
grafik

También me gusta a dónde va esto. Solo quiero votar por algún tipo de resaltado del nombre del módulo. De hecho, me gusta bastante el estilo en el que el mismo módulo está coloreado de la misma manera y recorre los colores (hay un problema de color de gráfico aquí si considera que dos líneas de seguimiento de pila son adyacentes como un borde de gráfico entre sus módulos). Sin embargo, desafortunadamente, no es bastante obvio lo que significa ese color. ¿Quizás colorear todos los nombres de los módulos en un solo color?

Esta alineación me parece bien.

Sigo pensando que tener las rutas más claramente distintas de las firmas ayudaría a dividir las cosas: 3 niveles de importancia, nombre / firma / ruta. Las macros de registro @info etc. las imprimen más claras que otras líneas.

Sería muy bueno tener nombres de variables. ¿Votaría que son menos importantes que la información de la firma, probablemente?

Tener los nombres de los módulos alineados a la izquierda te ayuda a escanearlos, aunque me entristece ver que los colores desaparecen.

Mis ojos parecen saber dónde encontrar cosas en este :)
¿Una línea en blanco entre módulos ocuparía demasiado espacio vertical?

Colorear filas con 2 colores diferentes para que las filas alternas tengan el mismo color, como se hace a menudo en las tablas, puede ayudar a mejorar la legibilidad.

Se destaca el ciclo de color de @ junto al nombre del módulo en lugar del nombre del módulo en sí (porque @ es un carácter bastante grande) sin competir demasiado con el nombre de la función resaltada.

A menudo he deseado los nombres de los parámetros, ya que le ayudan a encontrar el tipo de parámetro correcto sin tener que contarlos.

¿Podría la ruta (y quizás el nombre del módulo junto a ella) tener un brillo diferente al de los tipos? ¿Quizás solo coincidir con los nombres de los parámetros? (O todos con poca luz juntos si hace la sugerencia de mcabbott de hacer que los nombres sean más tenues que los tipos)

Podría reflejar explícitamente qué utiliza el registro, aunque idealmente con diferentes colores:

for i in 1:3
    printstyled("┌[", color=:magenta, bold=true); print(i); printstyled("] ", color=:magenta, bold=true)
    printstyled("get_ticklabels", bold=true); print("("); printstyled("style", color=:light_black); print("::AbstractPlotting.Automatic, "); printstyled("n", color=:light_black); print("::Int64")
    i!=2 ? println(")") : begin print(", "); printstyled("xs", color=:light_black);  print("::Array{Float64,2}, ");  printstyled("ys", color=:light_black);  print("::Array{Float64,1}, ");  printstyled("yes", color=:light_black);  print("::Bool, ");  printstyled("no", color=:light_black);  println("::Bool)") end
    printstyled("└ @ ", color=:magenta, bold=true); printstyled("MakieLayout", color=:magenta); printstyled(" ~/.julia/packages/MakieLayout/COfBu/src/lineaxis.jl:372", color=:light_black); println();
end
<strong i="6">@error</strong> join([join(rand('a':'z', rand(1:9))) for _ in 1:25]," ") pi

Editar: ahora con una línea más larga que envuelve y una imagen:
Screenshot 2020-05-28 at 20 21 48

Podría reflejar explícitamente qué utiliza el registro

Lo que no me gusta tanto de esto es que los saltos de línea que solo están allí debido al ancho específico de REPL no se transfieren bien si cambia el tamaño de su ventana / REPL (si desea dejar espacio para líneas más largas, por ejemplo ) o copie / pegue el texto en ventanas de diferente ancho

Sí, no propondría romper explícitamente las líneas para hacer que los marcadores sean continuos. De hecho, puede ser bueno dejar que las líneas envueltas se rompan y, por lo tanto, se vean diferentes. Principalmente un pensamiento sobre cómo vincular el color al nombre de la función y cómo hacerlo quizás menos molesto, si es parte del borde en lugar de verse como el encabezado más importante.

Debo decir que me gustó el color, pero puedo entender la preferencia por ser conservador con él.

Sin embargo, quiero dar mi apoyo a algo como

A menudo, el paquete exacto no es tan interesante como la naturaleza del código: ¿es el núcleo de julia, una biblioteca que estoy usando, la biblioteca que estoy desarrollando o un script? Podríamos tener cuatro colores: core / base / dev / stdlib, paquetes, paquetes actualmente ]dev ed y todos los demás (incluido el script / REPL). [...]

Dado que no estoy pirateando en la base y rara vez en los paquetes (como la mayoría de la gente, supongo), el 90% de los errores deben corregirse en mi script, el 9% en un paquete y el 1% en la base. Si cometí un error al llamar a una función que no necesito saber aquí exactamente en la base, se generó el error ya que no voy a entrar allí para solucionarlo de todos modos, necesito corregir mi código.

Así que agradecería algún ayuda visual para ver dónde dejo mi código (y tal vez también dónde dejo el código del paquete, yendo a la base) porque en la mayoría de los casos cualquier cosa después de eso puedo ignorarla con seguridad por ahora. Si no es a través del color, ¿tal vez con -------------------------------------------- o algo así? Solo debería haber 2-3 de esos.

Si los módulos se colorean, entonces quizás Base / Core debería omitirse y no se le debe dar color.

De hecho, me gusta bastante el estilo en el que el mismo módulo está coloreado de la misma manera y recorre los colores

Yo también estoy bien con eso. Si vamos a usar muchos colores, creo que deberían usarse para eso. También ayuda a identificar los límites entre el usuario y el código del paquete sin ocupar demasiado espacio vertical.

Si los módulos se colorean, entonces quizás Base / Core debería omitirse y no se le debe dar color.

Sí, Base y Core siempre pueden ser gris oscuro o algo así, dejando más colores para todos los demás :)

Si esto deja de funcionar perfectamente en 16 colores, entonces sería bueno convertirlos en un hash de los nombres de los módulos, para que pueda memorizar algunos de ellos.

¿O solo tiene dos colores, uno para Base / Core y otro para módulos externos?

Creo que no debería ser un gran problema cambiar los colores porque mi versión actual tiene 6 opciones sin escala de grises:

crayon"blue",
crayon"yellow",
crayon"red",
crayon"green",
crayon"cyan",
crayon"magenta",

También hay variantes claras, supongo, pero mi esquema de color en VSCode (Material) las tiene configuradas igual que los hermanos más oscuros, así que supongo que eso podría suceder en algunos esquemas. Pero, ¿qué probabilidad hay de que un seguimiento de pila pase por más de 6 módulos de biblioteca diferentes no básicos o no estándar? Por supuesto paquetes usan código de muchos módulos, pero en una pila particular, no debe haber tantos. Al menos eso no debería causar un gran problema al descifrar el seguimiento de la pila, incluso si hay colisiones de colores.

entonces sería bueno convertirlos en un hash de los nombres de los módulos, para que pueda memorizar algunos de ellos

Esto es realmente brillante.

Es genial ver a la gente trabajando en esto.
Me interesaría ver cómo se ve la alineación correcta de los nombres de las funciones:

 [1] get_ticklabels(code_lowered::...
 [2] get_ticklabels(real::AbstractPlotting
 [3] #105(mtime::
 [4] OnUpdate(vecormat::
 [5] #setindex!#5(atexti::

vs

 [1] get_ticklabels(code_lowered::...
 [2] get_ticklabels(real::AbstractPlotting
 [3]           #105(mtime::
 [4]       OnUpdate(vecormat::
 [5]   #setindex!#5(atexti::
 [6]      setindex!(mapslices

Puede ser más fácil para el ojo captar dónde comienzan los argumentos de la función y ofrecer ayuda para analizar la cadena de llamadas a la función sin perder mucho espacio. Todavía necesita ser compatible con colores, de lo contrario, la información y los argumentos de las ubicaciones ahogarían todo.

entonces sería bueno convertirlos en un hash de los nombres de los módulos, para que pueda memorizar algunos de ellos

Esto es realmente brillante.

Oh, hola verde azulado oscuro, mi viejo amigo ...

entonces sería bueno convertirlos en un hash de los nombres de los módulos, para que pueda memorizar algunos de ellos

Solía ​​hacer que emacs hiciera exactamente eso para los apodos de IRC. No funcionó tan bien porque a algunos de mis amigos se les asignó el mismo color y era más confuso que cualquier otra cosa, así que terminé codificando colores para mis amigos. No recomendaría ir por esa ruta, por muy genial que parezca. Tener un conjunto reducido de colores para cada tipo de código (por ejemplo, Julia, paquete, paquete desarrollado, usuario) parece más útil.

Aterricé en un esquema de color de editor que hace esto, y es moderadamente útil: todas las variables que de otra manera podrían ser azules son varios tonos de verde y azul, con cadenas y palabras clave, etc. diferentes. Quizás lo ideal sería algo así dentro de clases amplias como las que sugieres (por ejemplo, biblioteca estándar en rojo-violeta, descargada en verde-azul, dev-ed en naranja-amarillo, base en gris). ¡O quizás esto es demasiado trabajo!

otra iteración: traté de obtener nombres de variables allí, a pesar de que todo se siente súper hack para mí, ya que no estoy muy familiarizado con todos los aspectos internos. Cambié el color de los módulos porque parecía obtener una respuesta positiva en general, aunque es discutible cómo se deben asignar los colores. Pero con los colores, siento que el módulo de una entrada choca un poco con el nombre de la función de la siguiente. Así que introduje saltos de línea. Hace que todo sea más largo, por supuesto, pero me gusta el espacio adicional para respirar y la claridad.

grafik

Me gusta tu última muestra, es muy clara y legible :)

A continuación, se muestra un experimento que aplica el color del módulo a la "@" en lugar del nombre del módulo para reducir el conflicto que mencionaste con el nombre de la función, y prueba a resaltar los tipos para que la ruta se pueda distinguir un poco más fácilmente sin tener que introducir un espacio en blanco. líneas.

stacktrace2

@jkrumbiegel Eso es hermoso. Necesito esto en mi vida.

Me gustan esos azules suaves

@jkrumbiegel Genial, no estoy seguro de que se necesite el símbolo @, podría verse más limpio sin él. Si desea explicar cuál es esa información, también puede escribirla como sugirió Jeff:
in MakieLayout at ~/.julia/packages/MakieLayout/COfBu/src/lineaxis.jl:372

@jkrumbiegel ¡ Eso se ve genial! ¿Hay alguna forma de resaltar solo el nombre del archivo (no la ruta completa) y el número de línea? ¿Quizás un gris un poco más brillante?

¡Encantador! De hecho, me gustan mucho los saltos de línea; realmente ayudan visualmente y nuestros trazos de pila tienden a ser tan largos que tengo que desplazarme de todos modos, prefiero que sea claro que reducir el desplazamiento un poco.

Los :: resaltados son brillantes. Si tuviera que trazar una curva que muestre el contenido de información de cada carácter de la lista de parámetros frente a la posición del carácter, :: marcan exactamente los máximos locales de esa curva. Sé mirar a la izquierda de ellos para el nombre y a la derecha para la parte más importante del tipo, después de eso, el contenido de la información solo cae.

No estoy de acuerdo con este comentario: el resaltado debe enfatizar cosas importantes para que el ojo sepa qué leer, y el :: definitivamente no es algo importante que deba leer. Tal como está, el blanco es mucho más notable que el azul oscuro intenso. Distinguir los parámetros sería más claro con solo tener en blanco los nombres de los argumentos (quizás con la excepción de cuando no hay un argumento con nombre, en cuyo caso :: podría estar en blanco para delimitar los argumentos). Lo mismo ocurre con el número de línea, prefiero enfatizar el nombre del archivo que el número de línea.

Los nombres de los paquetes de colores corren el riesgo de eclipsar lo más importante, el nombre de la función, pero tenerlos en negrita y con saltos de línea realmente limita ese riesgo, ¡bien hecho!

Pensé en los :: mucho antes de hacerlos blancos. Por supuesto, los nombres de los argumentos y los tipos son la información real, por lo que podría pensar que deberían estar resaltados. Pero mi fuerte impresión al destacarlos es que llaman tu atención. Pero no es importante leer todos los nombres y tipos. Debería poder encontrar los que está buscando en una función específica. Cómo veo los pasos para leer un seguimiento de pila:

  1. Obtenga una descripción general
  2. ¿Qué función en qué módulo falló?
  3. ¿Qué otras funciones llamaron a esta función de qué otros módulos?
  4. ¿Existe un límite crítico entre mi propio código y el código base u otro paquete? ¿Dónde está?
  5. ¿Qué función hay en ese límite?
  6. ¿Qué tipos / argumentos se utilizaron? ¿Dónde termina un argumento y comienza el siguiente? Esto es especialmente difícil con tipos paramétricos largos en este momento.
  7. ¿Eso explica el error?
  8. Si esto no ayudó, revise todo con un peine fino

Entonces, en mi opinión, la información de tipo / argumento se usa solo después de orientar y comprender la estructura general. Una cosa que hay que entender sobre el resaltado es que no necesariamente facilita la búsqueda de cosas, solo si los resaltados son relativamente escasos. Así que creo que el :: resaltado no se interpone y capta tu atención hasta que comienzas a buscar información de tipo / variable. Y en ese paso le da a tus ojos ganchos para saltar, nada más, nada menos. Encuentro eso bastante eficiente.

Como nota al margen, no todos los argumentos tienen un nombre, por lo que resaltar los nombres de las variables no siempre le proporcionaría una buena separación. Creo que el :: siempre está ahí.

Parece una buena lista, mi principal queja es el punto 6, encontrar los espacios en las firmas de tipo largo. Imprimir :: superbrillante ayuda, aunque estoy de acuerdo en que es un poco extraño. Imprimir los nombres de los argumentos (o quizás algún marcador _1 posición

¿Cuántos niveles de resaltado están realmente disponibles? :white no se destacará en fondos claros, de hecho creo que podemos estar limitados a normal, negrita y :light_black (más colores). En este momento, el nombre de la función y la ruta están en negrita. En @error etc, la ruta es light_black, lo que parece genial.

Me gusta el uso del color para resaltar módulos. En algunas de las muestras anteriores, eclipsa al otro texto, pero ¿es esto cierto para los colores simples? En algunos temas diferentes, "Módulo" aquí está relativamente silenciado (y ::Array, ::Adjoint, ::Int claramente es la firma de nivel superior):

    printstyled("\nfunction", bold=true); print("(x::Array"); printstyled("{Float64,1}", color=:light_black); print(", y::Adjoint"); printstyled("{Float64,2,Array{Float64,2}}", color=:light_black); println(", z::Int64)")
    printstyled(" @ ", color=:light_black); printstyled("Module", color=:blue); printstyled(" ~/.julia/dev/Package/src/Package.jl:33 \n", color=:light_black)
end

Screenshot 2020-05-31 at 16 14 35

otra iteración: traté de obtener nombres de variables allí, a pesar de que todo se siente súper hack para mí, ya que no estoy muy familiarizado con todos los aspectos internos. Cambié el color de los módulos porque parecía obtener una respuesta positiva en general, aunque es discutible cómo se deben asignar los colores. Pero con los colores, siento que el módulo de una entrada choca un poco con el nombre de la función de la siguiente. Así que introduje saltos de línea. Hace que todo sea más largo, por supuesto, pero me gusta el espacio adicional para respirar y la claridad.

grafik

Puede ser un poco fuera de tema, pero dado que tenemos esto, ¿podemos tener un show más bonito para la salida de methods y methodswith ? También es un dolor.

Además, el color de los módulos podría ser un color atenuado, como no el amarillo exacto, sino el amarillo grisáceo. ¿O podemos tener esos colores configurables, como startup.jl ?

@jkrumbiegel ¡ Eso se ve genial! ¿Hay alguna forma de resaltar solo el nombre del archivo (no la ruta completa) y el número de línea? ¿Quizás un gris un poco más brillante?

Podría: https://github.com/JuliaLang/julia/issues/36026#issuecomment -634481656. Pero es un poco extraño para mí ya que el nombre del archivo es parte de la ruta, entonces, ¿por qué usa un color diferente? Por lo general, simplemente hago clic en la ruta y VSCode la abrirá por mí, por lo que no importa el nombre que tenga el archivo.

Dejé de usar Crayon.jl, ahora que ya no uso colores complejos. También ayuda con el tiempo de carga del paquete. Encontré una manera de mejorar la visibilidad del nombre del archivo y el número de línea sin que se volviera visualmente abrumador subrayando en gris oscuro. Eso también parece sensato, ya que estamos acostumbrados a que las rutas / enlaces estén subrayados. El blanco u otro resaltado era demasiado fuerte allí, negrita demasiado débil.

Además, cambié a colores claros como los primeros colores en el ciclador, lo que debería haber hecho en primer lugar, pero se ven iguales en mi tema, así que nunca me di cuenta. Esto debería ser mejor para temas donde el azul oscuro es apenas visible (aunque eso es culpa del tema).

He registrado este estilo como versión 0.2 en ClearStacktrace.jl para que podamos probarlo un poco más.

Dos ejemplos:

example 1

example 2

Ese es un trabajo realmente bueno.
Tiene los nombres de los parámetros más claros y los tipos más oscuros. ¿Resultó que se veía mejor / se leía mejor de esa manera que con los tipos más claros y los nombres más oscuros?

Sí, como los tipos suelen ser mucho más largos, no ayuda mucho hacerlos más ligeros.

Pensamientos aleatorios:

  • ¿Quizás reglas horizontales entre grupos de entradas de seguimiento de pila en el mismo módulo? tal vez demasiado ocupado mirando
  • también podría ser bueno en la parte superior del seguimiento de la pila, para separarlo claramente del mensaje de error

Todos estos son mucho mejores de lo que tenemos ahora ...

Dejé de usar Crayon.jl, ahora que ya no uso colores complejos. También ayuda con el tiempo de carga del paquete.

¿Causó un tiempo de carga significativo? Se carga bastante rápido por sí solo para mí

julia> <strong i="8">@time</strong> using Crayons
  0.014410 seconds (22.60 k allocations: 2.274 MiB)

Esta versión es genial, pongamos esto en Base.

De acuerdo: hagamos la última versión.

Gracias por hacer todo el trabajo aquí, @jkrumbiegel . Genial tener una versión que podamos probar ...

Y tenedor: supongo que creo que es un poco preocupante que el error rand(5) .* rand(7) plus ocupe 35 líneas. Así que hice https://github.com/mcabbott/ClearStacktrace.jl/tree/milder para probar. (Además de los problemas de color, etc., discutidos anteriormente). Esto es casi https://github.com/JuliaLang/julia/issues/36026#issuecomment -635294818 con más colores.

Tenga en cuenta que en el seguimiento de pila actual, los marcos de impresión 8-11 en ese ejemplo no se muestran (son parte del REPL y estarían en cada seguimiento de pila REPL).

De hecho, esto ha mejorado, lo cual es genial. Pero todavía va de 8 líneas (solo para el seguimiento de la pila) a 20 (ClearStacktrace 0.2). Existe una pequeña compensación entre lo bonito que es y no perder tu lugar.

Las rutas también se imprimen de forma mucho más compacta en Base, ./broadcast.jl:495 lugar de //Applications/Julia-1.5.app/Contents/Resources/julia/bin/../share/julia/base/broadcast.jl:495 , esto también reduciría la necesidad de líneas vacías.

Las rutas de la base se expanden a propósito para que se pueda hacer clic en ellas. Puede deshabilitar eso en ClearStacktrace. También podría hacer que las nuevas líneas sean opcionales para las personas a las que no les gustan. Podría ser simplemente una variable de entorno.

Y supongo que debo haber perdido la copia de la parte de la función que recorta los últimos fotogramas que nunca cambian.

Dejé de usar Crayon.jl, ahora que ya no uso colores complejos. También ayuda con el tiempo de carga del paquete. Encontré una manera de mejorar la visibilidad del nombre del archivo y el número de línea sin que se volviera visualmente abrumador subrayando en gris oscuro. Eso también parece sensato, ya que estamos acostumbrados a que las rutas / enlaces estén subrayados. El blanco u otro resaltado era demasiado fuerte allí, negrita demasiado débil.

Además, cambié a colores claros como los primeros colores en el ciclador, lo que debería haber hecho en primer lugar, pero se ven iguales en mi tema, así que nunca me di cuenta. Esto debería ser mejor para temas donde el azul oscuro es apenas visible (aunque eso es culpa del tema).

He registrado este estilo como versión 0.2 en ClearStacktrace.jl para que podamos probarlo un poco más.

Dos ejemplos:

example 1

example 2

¿Tiene curiosidad por saber por qué hay un / adicional en //Applications/Julia-1.4.app/ ?

Probablemente un error al dividirse y volver a unirse al camino

Dejé de usar Crayon.jl, ahora que ya no uso colores complejos. También ayuda con el tiempo de carga del paquete.

¿Causó un tiempo de carga significativo? Se carga bastante rápido por sí solo para mí

julia> <strong i="9">@time</strong> using Crayons

  0.014410 seconds (22.60 k allocations: 2.274 MiB)

No, en su mayoría lo eliminé porque no lo tendría en la base :) El tiempo de carga fue solo una suposición

Supongo que podría haber demasiadas líneas en blanco si tenemos muchos marcos de stacktrace como se muestra en https://github.com/JuliaLang/julia/issues/36026#issuecomment -636912686?

No para descarrilar la discusión (la última versión es genial y una gran mejora) pero sobre el tema de demasiadas nuevas líneas, el problema es que cuando trabajo en la terminal me parece mucho mejor imprimir el stacktrace "invertido" (como Propuse originalmente en https://github.com/JuliaLang/julia/pull/18228) como:

...
[3] frame
[2] frame
[1] frame
Error: Some error happened
blah blah

La información más importante es el mensaje de error en sí y los marcos hacia la parte superior de la pila (más cerca del error) e imprimirlo en este orden que siempre estará visible sin desplazarse. En este momento, con frecuencia tengo que desplazarme hacia arriba para ver incluso el mensaje de error y no solo la cola de un stacktrace.

Sin embargo, al leer un stacktrace en una webstite que se ha copiado y pegado desde la terminal, desea el orden opuesto porque se desplaza de arriba hacia abajo en lugar de de abajo hacia arriba como lo hace en una terminal ... Es un poco complicado obtener una buen diseño para ambos casos.

Sin embargo, al leer un stacktrace en una webstite que se ha copiado y pegado desde la terminal, desea el orden opuesto porque se desplaza de arriba hacia abajo en lugar de de abajo hacia arriba como lo hace en una terminal ... Es un poco complicado obtener una buen diseño para ambos casos.

De hecho, tuve un código en ClearStacktrace.jl por un momento que me permitió reimprimir el último stacktrace. Había imaginado eso para cortar los tipos superlargos con un máximo de caracteres y poder reimprimir en su totalidad si se necesitaba toda la información. Pero su caso de uso también sería interesante. Puedo imaginar un reprint(inverted = true) o incluso reprint(html = true) donde imprimiría una versión html que retendría el color para pegar en un sitio web.

Además, estoy de acuerdo en que, dada la dirección de desplazamiento, podría tener sentido invertir todo de forma predeterminada.

ipython imprime marcos en el orden opuesto y, a pesar de no tener que desplazarme, siempre lo he encontrado inexplicablemente confuso. ¿Quizás se deba a mi experiencia previa con gdb y otros sistemas donde el marco más interno está en la parte superior, o quizás otras personas también se sienten así?

Hablando de gdb, tienen una solución razonable para trazos muy largos con su buscapersonas: "presione enter para más marcos".

Por cierto, me encanta el último diseño visual en https://github.com/JuliaLang/julia/issues/36026#issuecomment -636912686 y estaría extremadamente feliz si fusionáramos eso. Cambiar el orden de los fotogramas o agregar funciones interactivas parecen problemas separados.

Con respecto a los nombres de archivo, espero que eventualmente podamos usar secuencias OSC de hipervínculos de terminal (¡ sí, los hipervínculos en terminales son ampliamente compatibles! ) Y tener una forma para que el editor del usuario lo capte.

Hablando de encontrar el "marco más interno", utilizo suficientes lenguajes en el curso de mi trabajo que nunca puedo recordar si debería estar buscando en la parte superior o inferior de un stacktrace para mi código en un lenguaje en particular. Así que termino escaneando mirando el nombre del archivo hasta que veo uno que reconozco. El subrayado que se muestra aquí ayudaría, por lo que esta es una clara mejora. Pero todavía me pregunto si hay una buena forma de decir si debería estar mirando hacia arriba o hacia abajo. En principio, imprimir YOUR CODE HERE en un extremo y OTHER CODE HERE en el otro me ayudaría, pero no parece muy elegante.

Hice un PR para Base aquí https://github.com/JuliaLang/julia/pull/36134
Por lo que puedo decir, funciona, pero necesitaré ayuda para prepararlo para la fusión.

¿Hay alguna forma de omitir los parámetros de tipo? El problema que vemos muchas veces es que la cantidad de parámetros de tipo en DiffEq, ForwardDiff, etc. puede hacer que las cosas sean ... desalentadoras. Si de forma predeterminada solo dice Dual , excepto en el caso de que haya un envío a otros métodos debido a los parámetros de tipo, creo que reduciría el 90% del ruido en la mayoría de los rastros de pila que leo (y en en los otros casos, la sugerencia de @timholy es realmente lo que se requiere, ya que generalmente se trata de hacer tipos o parámetros de tipo coincidentes)

Si corresponden a algún alias de tipo existente, desaparecerán automáticamente ahora (# 36107). De lo contrario, indican posibles cuellos de botella en el rendimiento de la compilación, por lo que posiblemente valga la pena investigarlos.

Esto ya está hecho.

Para algunas personas, pero la mayoría de las personas simplemente se confunden cuando imprime un tipo que ocuparía 3 páginas de papel impreso, por lo que probablemente debería ser algo opcional. Abriré otro tema para discutir eso.

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

StefanKarpinski picture StefanKarpinski  ·  3Comentarios

yurivish picture yurivish  ·  3Comentarios

wilburtownsend picture wilburtownsend  ·  3Comentarios

felixrehren picture felixrehren  ·  3Comentarios

m-j-w picture m-j-w  ·  3Comentarios