ndmitchell / shake

Shake build system
http://shakebuild.com
Other
772 stars 118 forks source link

No way to have a command run with a terminal #212

Closed deepfire closed 9 years ago

deepfire commented 9 years ago

This effectively prevents colorized output from recent gcc / clang from being available:

    phony "info" $ do
      cmd "ls" "--color=auto"

Additionally, it effectively prevents one from launching a useful sub-shell for the user -- a shell is run, but it has absolutely no terminal handling.

Apparently this requires jumping through the PTY hoops, which Shake doesn't do yet.

ndmitchell commented 9 years ago

Thanks for the report. You can certainly use other system command calls from Shake, for example:

System.Cmd.system "ls --color=auto"

Do any Haskell functions get this right? What PTY hoops are required? Under the hood, Shake uses System.Process and the process library - can you configure that to use PTY? Or does it need upgrading to do the PTY hoops? (I'm a Windows user primarily, so not really sure about PTY details)

deepfire commented 9 years ago

Thank you!

System.Cmd.system "bash" works just fine!

deepfire commented 9 years ago

As to the PTY details, I'm not really sure, never touched that particular area.

For the record, neither Shelly, nor Turtle get this right -- I have submitted bug reports to them as well..

ndmitchell commented 9 years ago

If you call:

cmd Shell "ls --color=auto"

Does that work? That shares some characteristics with system.

deepfire commented 9 years ago

No, it doesn't -- same plain, PTY-less stdio, apparently..

ndmitchell commented 9 years ago

OK, observing the code, my best guess is that if you capture the standard handles at all it will break. Shake by default captures stderr so it can use it in the exception message. If you turn off the exception message capturing it still doesn't work because Shake doesn't have an optimisation to inherit the handles in that case, it just captures stderr and throws it away. I was working on such an optimization last night for other reasons, but it sounds like with that I'll be apply to have a PTY flag which disables enough stuff for this feature to work.

refi64 commented 9 years ago

FYI, you can use --fcolor-diagnostics for force colors in Clang, and maybe GCC. That's what I do.

deepfire commented 9 years ago

@kirbyfan64, for gcc I use -fdiagnostics-color=always. But getting the colors sequences to be emitted isn't the problem.. The problem is to get a context, where those color sequences will get interpreted.

ndmitchell commented 9 years ago

With the HEAD version of Shake this might be possible. If you pass WithStderr False then it should just inherit all file descriptors, and my guess is that is what makes system work.

deepfire commented 9 years ago

I have tested it in 0.15 and I can confirm that:

    phony "lol" $ do
      cmd (WithStderr False) "bash"

works with a full terminal.

ndmitchell commented 9 years ago

Thanks for testing, I'll leave this ticket to update the docs to include the magic required.

ndmitchell commented 9 years ago

I've documented it with:

By default the @stderr@ stream will be captured for use in error messages, and also echoed. To only echo pass @'WithStderr' 'False'@, which causes no streams to be captured by Shake, and certain programs (e.g. @gcc@) to detect they are running in a terminal.

Please let me know if that can be improved or is incorrect (I'm mostly guessing about what half these words mean).

deepfire commented 9 years ago

Neil, I have tested shake-0.15, and to my surprise, (WithStderr False) is no longer necessary -- colored output, as well as subshells work perfectly well with captured stderr.

I have no idea what's going on.

ndmitchell commented 9 years ago

I completely rewrote the internals of the cmd stuff in v0.15, so it's no great shock - I guess one of the things I did had that side effect.

deepfire commented 9 years ago

It's actually very pleasant, since it removes the need to choose between error logging and functioning of pty-based commands : -)

Thank you!

afranchuk commented 6 years ago

I'm running 0.16.x, and I don't see this behavior. If WithStderr == True (the default), there is no color output. I wonder why it started working for @deepfire... if it was indeed something specifically in 0.15, but something that was changed/removed in 0.16, that would be interesting.

EDIT: Maybe a combination of WithStderr True and Shell would do the trick? Unfortunately Shell is not an option for me, but it might be for others.

I think the easiest way to achieve this might be through System.Posix.Pty. Although since it relies on System.Posix.Terminal, it probably won't work for windows.

An issue I have with the WithStderr False solution is that it prevents output buffering, so the user is not presented with a nice error message (and it could be interleaved with other information/outputs in the terminal).