Explorar o código

Add `core:terminal`

Feoramund hai 3 meses
pai
achega
30c1b88741

+ 4 - 0
core/terminal/doc.odin

@@ -0,0 +1,4 @@
+/*
+This package is for interacting with the command line interface of the system.
+*/
+package terminal

+ 104 - 0
core/terminal/terminal.odin

@@ -0,0 +1,104 @@
+package terminal
+
+import "core:os"
+import "core:strings"
+
+/*
+This describes the range of colors that a terminal is capable of supporting.
+*/
+Color_Depth :: enum {
+	None,       // No color support
+	Three_Bit,  // 8 colors
+	Four_Bit,   // 16 colors
+	Eight_Bit,  // 256 colors
+	True_Color, // 24-bit true color
+}
+
+/*
+Returns true if the file `handle` is attached to a terminal.
+
+This is normally true for `os.stdout` and `os.stderr` unless they are
+redirected to a file.
+*/
+@(require_results)
+is_terminal :: proc(handle: os.Handle) -> bool {
+	return _is_terminal(handle)
+}
+
+/*
+Get the color depth support for the terminal.
+*/
+@(require_results)
+get_color_depth :: proc() -> Color_Depth {
+	// Reference documentation:
+	//
+	// - [[ https://no-color.org/ ]]
+	// - [[ https://github.com/termstandard/colors ]]
+	// - [[ https://invisible-island.net/ncurses/terminfo.src.html ]]
+
+	// Respect `NO_COLOR` above all.
+	if no_color, ok := os.lookup_env("NO_COLOR"); ok {
+		defer delete(no_color)
+		if no_color != "" {
+			return .None
+		}
+	}
+
+	// `COLORTERM` is non-standard but widespread and unambiguous.
+	if colorterm, ok := os.lookup_env("COLORTERM"); ok {
+		defer delete(colorterm)
+		// These are the only values that are typically advertised that have
+		// anything to do with color depth.
+		if colorterm == "truecolor" || colorterm == "24bit" {
+			return .True_Color
+		}
+	}
+
+	if term, ok := os.lookup_env("TERM"); ok {
+		defer delete(term)
+		if strings.contains(term, "-truecolor") {
+			return .True_Color
+		}
+		if strings.contains(term, "-256color") {
+			return .Eight_Bit
+		}
+		if strings.contains(term, "-16color") {
+			return .Four_Bit
+		}
+
+		// The `terminfo` database, which is stored in binary on *nix
+		// platforms, has an undocumented format that is not guaranteed to be
+		// portable, so beyond this point, we can only make safe assumptions.
+		//
+		// This section should only be necessary for terminals that do not
+		// define any of the previous environment values.
+		//
+		// Only a small sampling of some common values are checked here.
+		switch term {
+		case "ansi":       fallthrough
+		case "konsole":    fallthrough
+		case "putty":      fallthrough
+		case "rxvt":       fallthrough
+		case "rxvt-color": fallthrough
+		case "screen":     fallthrough
+		case "st":         fallthrough
+		case "tmux":       fallthrough
+		case "vte":        fallthrough
+		case "xterm":      fallthrough
+		case "xterm-color":
+			return .Three_Bit
+		}
+	}
+
+	return .None
+}
+
+/*
+This is true if the terminal is accepting any form of colored text output.
+*/
+color_enabled: bool
+
+@(init, private)
+init_terminal_status :: proc() {
+	color_enabled = get_color_depth() > .None
+}

+ 9 - 0
core/terminal/terminal_posix.odin

@@ -0,0 +1,9 @@
+#+build linux, darwin, netbsd, openbsd, freebsd, haiku
+package terminal
+
+import "core:os"
+import "core:sys/posix"
+
+_is_terminal :: proc(handle: os.Handle) -> bool {
+	return bool(posix.isatty(posix.FD(handle)))
+}

+ 9 - 0
core/terminal/terminal_windows.odin

@@ -0,0 +1,9 @@
+package terminal
+
+import "core:os"
+import "core:sys/windows"
+
+_is_terminal :: proc(handle: os.Handle) -> bool {
+	mode: windows.DWORD
+	return bool(windows.GetConsoleMode(windows.HANDLE(handle), &mode))
+}

+ 3 - 0
examples/all/all_main.odin

@@ -129,6 +129,8 @@ import strings          "core:strings"
 import sync             "core:sync"
 import testing          "core:testing"
 
+import terminal         "core:terminal"
+
 import edit             "core:text/edit"
 import i18n             "core:text/i18n"
 import match            "core:text/match"
@@ -257,6 +259,7 @@ _ :: strconv
 _ :: strings
 _ :: sync
 _ :: testing
+_ :: terminal
 _ :: scanner
 _ :: i18n
 _ :: match