edubart / nelua-lang

Minimal, efficient, statically-typed and meta-programmable systems programming language heavily inspired by Lua, which compiles to C and native code.
https://nelua.io
MIT License
1.99k stars 64 forks source link

Executables reflect compile-time isatty conditions #237

Closed jrfondren closed 10 months ago

jrfondren commented 10 months ago

Bug description

The following error has bold red and white colors in it:

$ nelua -i 'require("io") io.printf("looking at: %d\n", "a string")'
/home/jfondren/nelua/nelua-lang/lib/stringbuilder.nelua:349:12: runtime error: invalid format for argument
    assert(false, 'invalid format for argument')
           ^~~~~

Aborted

The error resulting from the following does not:

nelua -i 'require("io") io.printf("looking at: %d\n", "a string")' | cat

This is very reasonable behavior, but the decision is baked into the executable, which results in executables including terminal control codes in their runtime errors even when the message isn't going to the terminal.

Workaround

If unwanted codes are a problem, the simplest workaround is to add |cat to the end of nelua builds, so that they're always disabled.

Environment

x86_64 linux Nelua 0.2.0-dev Build number: 1588 Git date: 2023-09-16 16:20:44 -0300 Git hash: 596fcca5c77932da8a07c249de59a9dff3099495 Semantic version: 0.2.0-dev.1588+596fcca5 Copyright (C) 2019-2022 Eduardo Bart (https://nelua.io/)

edubart commented 10 months ago

By default, the functions error, assert and check add source location and color codes, to make error messages more readable, both color codes and source location are dependent on the host environment the program is being compiled.

You could disable that with noassertloc pragma, however I have recently renamed the pragma to noerrorloc in commit https://github.com/edubart/nelua-lang/commit/b385d4134cb39b1bb2b5df8a2c8d72d789f89d8d.

So after updating, if you want to have a more reproducible executable when compiling in different environments, compile with -Pnoerrorloc to disable color codes and source location for all error messages in the final executable.

If you want to just disable colored output, you can compile with --no-color, it will disable coloring for the nelua compiler itself, but also disable the use of color codes in the final executable.

jrfondren commented 10 months ago

The problem isn't reproducible executables, it's that executables emit color codes when they shouldn't do so. Nelua itself tests isatty for the same reason that the built executable should: because colors are nice to have at the terminal, and a problem to have in every other case - in a log, in an editor, in a pastebin when copying output to a github issue, etc.

Normally you would always want colors in your error messages, but if you give someone an executable that can't turn them off, in the same way that the nelua compiler turns them off, then you get bug reports like this:

/home/jfondren/nelua/nelua-lang/lib/stringbuilder.nelua^[[1m:349:12: ^[[31m^[[1mruntime error: ^[[0m^[[1minvalid format for argument^[[0m
    assert(false, 'invalid format for argument')
           ^[[1m^[[32m^^[[0m^[[35m~~~~^[[0m
edubart commented 10 months ago

for the same reason that the built executable should

Detecting if the terminal is capable of printing colors at runtime would introduce a lot of baggage to every executable built by Nelua, with specific OS calls (such as isatty), something Nelua tries to avoid in favor of simplicity and compactness. Most of Nelua code is not dependent on OS functions, and even standard C functions are minimized, some people experiment with Nelua for building OS or to target consoles where there no standard C library available, this is why most Nelua builtin functions and standard library is made to be "freestanding".

If you give someone an executable that can't turn them off

Then that's a problem of the user who is distributing the executable, he has to choose to completely disable colors or not when building.

If the assert behavior is not ideal, it's possible to implement your own assert function with some runtime detection for colors.