1 /// Utils to work with terminal
2 module sily.terminal;
3 
4 public import sily.terminal.windows;
5 public import sily.terminal.posix;
6 
7 import std.stdio: stdin, stdout, File;
8 import std.process: spawnProcess, wait;
9 import std.conv: to;
10 import std.file: tempDir, remove, exists, readText;
11 import std.array: popBack;
12 
13 import core.stdc.stdlib: getenv;
14 
15 import sily.path: fixPath;
16 
17 ColorSupport terminalColorSupport(ColorSupport defaultColor = ColorSupport.ansi8) {
18     string env = getenv("COLORTERM").to!string;
19 
20     if (env == "truecolor") {
21         return ColorSupport.truecolor;
22     } else
23     if (env == "24bit") {
24         return ColorSupport.ansi256;
25     } else 
26     if (env == "8bit") {
27         return ColorSupport.ansi8;
28     }
29     
30     string fp = (tempDir ~ "/sily-dlang-terminal-temp.txt").fixPath();
31     
32     // TODO: rewrite with execute
33     File tf = File(fp, "w+");
34     wait(spawnProcess(["tput", "colors"], stdin, tf));
35     tf.close();
36     string _out = fp.readText();
37     if (fp.exists()) fp.remove();
38     _out.popBack();
39 
40     if (_out == "256") return ColorSupport.ansi256;
41     if (_out == "8") return ColorSupport.ansi8;
42 
43     return defaultColor;
44 }
45 
46 enum ColorSupport {
47      ansi8, ansi256, truecolor
48 }
49 
50 import core.stdc.stdlib: cexit = exit;
51 import core.thread: Thread;
52 import core.time: dmsecs = msecs;
53 
54 /// Forcefully closes application
55 void exit(ErrorCode code = ErrorCode.general) {
56     cexit(cast(int) code);
57 }
58 
59 /// Alias to ErrorCode enum
60 alias ExitCode = ErrorCode;
61 
62 /// Enum containing common exit codes
63 enum ErrorCode {
64     /// Program completed correctly
65     success = 0,
66     /// Catchall for general errors (misc errors, such as `x / 0`)
67     general = 1,
68     /// Operation not permitted (missing keyword/command or permission problem)
69     noperm = 2,
70     /// Command invoked cannot execute (permission problem or command is not executable)
71     noexec = 126,
72     /// Command not found (possible problem with `$PATH` or typo)
73     notfound = 127,
74     /// Invalid argument to exit (see ErrorCode.nocode)
75     noexit = 128,
76     /// Fatal error (further execution is not possible or might harm the OS)
77     fatal = 129,
78     /// Terminated with `Ctrl-C`
79     sigint = 130,
80     /// Exit status out of range (maximal exit code)
81     nocode = 255
82 }
83 
84 /// Sleeps for set amount of msecs
85 void sleep(uint msecs) {
86     Thread.sleep(msecs.dmsecs);
87 }