Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support truecolor in a terminal #6936

Merged
merged 36 commits into from Jan 18, 2018
Merged

Support truecolor in a terminal #6936

merged 36 commits into from Jan 18, 2018

Conversation

data-man
Copy link
Contributor

Currently for *nix only.
Example output (in Konsole):
screenshot_20171217_153940

@Araq
Copy link
Member

Araq commented Dec 17, 2017

I don't mind the feature but IMO terminal.nim should be as stateless as possible, setBackgroundColor and friends are a design invented before we got subroutine parameters.

@data-man
Copy link
Contributor Author

Example's code:

import terminal

const Nim = "Efficient and expressive programming."

var
  fg = colYellow
  bg = colBlue
  int = 1.0

for i in 1..10:
  styledEcho bgColor, bg, fgColor, fg, Nim
  int -= 0.05
  fg = intensity(fg, int)

styledEcho resetStyle

@Araq
How can I improve the procs?

@Araq
Copy link
Member

Araq commented Dec 18, 2017

Hmm, my point was that styledEcho needs to support it but it looks like it already does. Maybe try to not export these?

@data-man
Copy link
Contributor Author

I added the setForegroundColor*(stdout, color) and setBackgroundColor*(color: Color) templates only for consistency, because there is already setForegroundColor*(fg: ForegroundColor, bright = false), setBackgroundColor*(bg: BackgroundColor, bright=false) and others.

@data-man
Copy link
Contributor Author

Maybe it's still useful to someone: Colours in terminal :)

@Araq
Copy link
Member

Araq commented Dec 18, 2017

If Windows does not support it, make it not compile on Windows, this should all be within an when defined(posix) then.

@data-man
Copy link
Contributor Author

Windows support added. (Tested on Windows 10 in VirtualBox).

var
trueColorIsSupported = false
fgSetColor = true
colorsFGCache = initTable[Color, string]()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Breaks multi-threading.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is done?

from strutils import toLowerAscii
import tables
import colors
export colors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think terminal should export colors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

when defined(windows):
var mode: DWORD = 0
discard getConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), addr(mode))
mode = mode or ENABLE_VIRTUAL_TERMINAL_PROCESSING
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change ... Previously no escape sequences were interpreted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe to add (enable|disable|isSupported)TrueColor procs?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change, please don't do this at initialization but only if requested via enableTrueColor.

trueColorIsSupported = setConsoleMode(getStdHandle(STD_OUTPUT_HANDLE), mode) != 0
else:
when compileOption("taintmode"):
trueColorIsSupported = string(getEnv("COLORTERM")).toLowerAscii() in ["truecolor", "24bit"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This version works for a disabled taint mode too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -1059,6 +1059,28 @@ else:
lpNumberOfEventsRead: ptr cint): cint
{.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}

const
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are all terminal specific and so should be in terminal.nim.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@data-man
Copy link
Contributor Author

Hanging a tests on AppVeyor after last commit :(

@@ -677,3 +750,18 @@ when not defined(testing) and isMainModule:
stdout.setForeGroundColor(fgBlue)
stdout.writeLine("ordinary text")
stdout.resetAttributes()

fgSetColor = true
colorsFGCache = initTable[Color, string]()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only works for the main thread. ;-)

@data-man data-man closed this Dec 21, 2017
@data-man data-man reopened this Dec 21, 2017
styleCache = newTable[int, string]()

fgSetColor = true
colorsFGCache = newTable[Color, string]()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only runs for the main thread!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I really do not understand what is wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He means that the colorsFGCache will only be initialised in the main thread. If you try using it from another thread it will be nil and your code will likely fail.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
I looked at the code in the /tests/parallel/tsendtwice.nim.
It works there. Or not?

@data-man
Copy link
Contributor Author

Maybe disable caching when the thread mode is defined?

@data-man
Copy link
Contributor Author

Corrections for Windows.
TrueColor disabled by default.

@data-man
Copy link
Contributor Author

Hm, true color for Windows < 10 probably can be used with a non-standard terminals, e.g. ConEmu.

@data-man
Copy link
Contributor Author

Added support for non-standard terminals.
Tested on Windows 8.1 with ConEmu.

var
fg = colYellow
bg = colBlue
int = 1.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a variable called 'int' that is of type float? Come on. ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intensity :-)

Copy link
Contributor

@dom96 dom96 Jan 18, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be changed. Don't name your variables after types.

changelog.md Outdated
bg = colBlue
int = 1.0

enableTrueColor()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be called enableTrueColors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@johannschopplich
Copy link

Quite looking forward to a merge on this pull request. 👍


proc setForegroundColor*(f: File, color: Color) =
## Sets the terminal's foreground true color.
if trueColorIsEnabled:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be assert(trueColorIsEnabled, "enableTrueColors() must be called before setForegroundColor")?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Because a true color may be used for debugging with a colored messages.


proc setBackgroundColor*(f: File, color: Color) =
## Sets the terminal's background true color.
if trueColorIsEnabled:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same answer.

styleCache: Table[int, string]

var
trueColorIsSupported {.threadvar.}: bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These threadvars are still not correct!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't understand: why a threadvars in other modules are correct?

fgSetColor = true

when defined(windows):
import os
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this logic should be moved into enableTrueColors!

gFG = 0
gBG = 0
gFG {.threadvar.}: int
gBG {.threadvar.}: int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is far too many global thread variables in this module (and this isn't your fault). But these should all be put into a single State object, eventually at least.

gFG {.threadvar.}: int
gBG {.threadvar.}: int

proc getStyleStr(style: int): string =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're losing type safety here. The styleCache can be changed to an array[Style, string]

@Araq Araq merged commit 7ce3812 into nim-lang:devel Jan 18, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants