mirror of https://github.com/adamdruppe/arsd.git
win32 console as a runtime option
This commit is contained in:
parent
405bd59c9d
commit
65d5983303
427
terminal.d
427
terminal.d
|
@ -2,6 +2,9 @@
|
|||
// for VT on Windows P s = 1 8 → Report the size of the text area in characters as CSI 8 ; height ; width t
|
||||
// could be used to have the TE volunteer the size
|
||||
|
||||
// FIXME: have some flags or formal api to set color to vtsequences even on pipe etc on demand.
|
||||
|
||||
|
||||
// FIXME: the resume signal needs to be handled to set the terminal back in proper mode.
|
||||
|
||||
/++
|
||||
|
@ -314,6 +317,8 @@ version(Posix) {
|
|||
|
||||
version(TerminalDirectToEmulator) {
|
||||
version=VtEscapeCodes;
|
||||
version(Windows)
|
||||
version=Win32Console;
|
||||
} else version(Windows) {
|
||||
version(VtEscapeCodes) {} // cool
|
||||
version=Win32Console;
|
||||
|
@ -328,11 +333,7 @@ version(Windows)
|
|||
}
|
||||
|
||||
version(Win32Console) {
|
||||
private {
|
||||
enum RED_BIT = 4;
|
||||
enum GREEN_BIT = 2;
|
||||
enum BLUE_BIT = 1;
|
||||
}
|
||||
__gshared bool UseWin32Console = true;
|
||||
|
||||
pragma(lib, "user32");
|
||||
}
|
||||
|
@ -353,20 +354,7 @@ version(Posix) {
|
|||
|
||||
version(VtEscapeCodes) {
|
||||
|
||||
enum UseVtSequences = true;
|
||||
|
||||
version(TerminalDirectToEmulator) {
|
||||
private {
|
||||
enum RED_BIT = 1;
|
||||
enum GREEN_BIT = 2;
|
||||
enum BLUE_BIT = 4;
|
||||
}
|
||||
} else version(Windows) {} else
|
||||
private {
|
||||
enum RED_BIT = 1;
|
||||
enum GREEN_BIT = 2;
|
||||
enum BLUE_BIT = 4;
|
||||
}
|
||||
__gshared bool UseVtSequences = true;
|
||||
|
||||
struct winsize {
|
||||
ushort ws_row;
|
||||
|
@ -533,10 +521,10 @@ enum Bright = 0x08;
|
|||
/// See also: [Bright]
|
||||
enum Color : ushort {
|
||||
black = 0, /// .
|
||||
red = RED_BIT, /// .
|
||||
green = GREEN_BIT, /// .
|
||||
red = 1, /// .
|
||||
green = 2, /// .
|
||||
yellow = red | green, /// .
|
||||
blue = BLUE_BIT, /// .
|
||||
blue = 4, /// .
|
||||
magenta = red | blue, /// .
|
||||
cyan = blue | green, /// .
|
||||
white = red | green | blue, /// .
|
||||
|
@ -621,20 +609,7 @@ struct Terminal {
|
|||
} else {
|
||||
if(what != currentCursor_ || force == ForceOption.alwaysSend) {
|
||||
currentCursor_ = what;
|
||||
version(Win32Console) {
|
||||
final switch(what) {
|
||||
case TerminalCursor.DEFAULT:
|
||||
SetConsoleCursorInfo(hConsole, &originalCursorInfo);
|
||||
break;
|
||||
case TerminalCursor.insert:
|
||||
case TerminalCursor.block:
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.dwSize = what == TerminalCursor.insert ? 1 : 100;
|
||||
SetConsoleCursorInfo(hConsole, &info);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(UseVtSequences) {
|
||||
final switch(what) {
|
||||
case TerminalCursor.DEFAULT:
|
||||
if(terminalInFamily("linux"))
|
||||
|
@ -657,6 +632,19 @@ struct Terminal {
|
|||
writeStringRaw("\033[2 q");
|
||||
break;
|
||||
}
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
final switch(what) {
|
||||
case TerminalCursor.DEFAULT:
|
||||
SetConsoleCursorInfo(hConsole, &originalCursorInfo);
|
||||
break;
|
||||
case TerminalCursor.insert:
|
||||
case TerminalCursor.block:
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.dwSize = what == TerminalCursor.insert ? 1 : 100;
|
||||
SetConsoleCursorInfo(hConsole, &info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,12 +715,20 @@ struct Terminal {
|
|||
}
|
||||
|
||||
bool terminalInFamily(string[] terms...) {
|
||||
version(Win32Console) if(UseWin32Console)
|
||||
return false;
|
||||
|
||||
// we're not writing to a terminal at all!
|
||||
if(!stdoutIsTerminal || !stdinIsTerminal)
|
||||
return false;
|
||||
|
||||
import std.process;
|
||||
import std.string;
|
||||
version(TerminalDirectToEmulator)
|
||||
auto term = "xterm";
|
||||
else
|
||||
auto term = environment.get("TERM");
|
||||
|
||||
foreach(t; terms)
|
||||
if(indexOf(term, t) != -1)
|
||||
return true;
|
||||
|
@ -745,12 +741,15 @@ struct Terminal {
|
|||
// work the way they're advertised. I just have to best-guess hack and hope it
|
||||
// doesn't break anything else. (If you know a better way, let me know!)
|
||||
bool isMacTerminal() {
|
||||
return false;
|
||||
/+
|
||||
// it gives 1,2 in getTerminalCapabilities...
|
||||
// FIXME
|
||||
import std.process;
|
||||
import std.string;
|
||||
auto term = environment.get("TERM");
|
||||
return term == "xterm-256color";
|
||||
+/
|
||||
}
|
||||
} else
|
||||
bool isMacTerminal() { return false; }
|
||||
|
@ -904,6 +903,9 @@ struct Terminal {
|
|||
|
||||
// Looks up a termcap item and tries to execute it. Returns false on failure
|
||||
bool doTermcap(T...)(string key, T t) {
|
||||
if(!stdoutIsTerminal)
|
||||
return false;
|
||||
|
||||
import std.conv;
|
||||
auto fs = getTermcap(key);
|
||||
if(fs is null)
|
||||
|
@ -1060,7 +1062,9 @@ struct Terminal {
|
|||
+/
|
||||
bool saveCursorPosition()
|
||||
{
|
||||
version (Win32Console)
|
||||
if(UseVtSequences)
|
||||
return doTermcap("sc");
|
||||
else version (Win32Console) if(UseWin32Console)
|
||||
{
|
||||
flush();
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
|
@ -1074,14 +1078,16 @@ struct Terminal {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
return doTermcap("sc");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
bool restoreCursorPosition()
|
||||
{
|
||||
version (Win32Console)
|
||||
if(UseVtSequences)
|
||||
// FIXME: needs to update cursorX and cursorY
|
||||
return doTermcap("rc");
|
||||
else version (Win32Console) if(UseWin32Console)
|
||||
{
|
||||
if (cursorPositionStack.length > 0)
|
||||
{
|
||||
|
@ -1093,11 +1099,7 @@ struct Terminal {
|
|||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: needs to update cursorX and cursorY
|
||||
return doTermcap("rc");
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
// only supported on my custom terminal emulator. guarded behind if(inlineImagesSupported)
|
||||
|
@ -1288,18 +1290,29 @@ struct Terminal {
|
|||
} catch(Exception e) {
|
||||
if(!integratedTerminalEmulatorConfiguration.fallbackToDegradedTerminal)
|
||||
throw e;
|
||||
|
||||
}
|
||||
} else {
|
||||
this.usingDirectEmulator = true;
|
||||
}
|
||||
|
||||
if(!usingDirectEmulator) {
|
||||
if(integratedTerminalEmulatorConfiguration.preferDegradedTerminal)
|
||||
this.usingDirectEmulator = false;
|
||||
|
||||
// FIXME is this really correct logic?
|
||||
if(!stdinIsTerminal || !stdoutIsTerminal)
|
||||
this.usingDirectEmulator = false;
|
||||
|
||||
if(usingDirectEmulator) {
|
||||
version(Win32Console)
|
||||
UseWin32Console = false;
|
||||
UseVtSequences = true;
|
||||
} else {
|
||||
version(Posix) {
|
||||
posixInitialize(type, 0, 1, null);
|
||||
return;
|
||||
} else {
|
||||
throw new Exception("Total wtf - are you on a windows system without a gui?!?");
|
||||
} else version(Win32Console) {
|
||||
UseVtSequences = false;
|
||||
UseWin32Console = true; // this might be set back to false by windowsInitialize but that's ok
|
||||
windowsInitialize(type);
|
||||
return;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
@ -1377,8 +1390,46 @@ struct Terminal {
|
|||
this(ConsoleOutputType type, int fdIn = 0, int fdOut = 1, int[] delegate() getSizeOverride = null) {
|
||||
_initialized = true;
|
||||
posixInitialize(type, fdIn, fdOut, getSizeOverride);
|
||||
} else version(Win32Console)
|
||||
this(ConsoleOutputType type) {
|
||||
windowsInitialize(type);
|
||||
}
|
||||
|
||||
version(Win32Console)
|
||||
void windowsInitialize(ConsoleOutputType type) {
|
||||
_initialized = true;
|
||||
if(UseVtSequences) {
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
initializeVt();
|
||||
} else {
|
||||
if(type == ConsoleOutputType.cellular) {
|
||||
goCellular();
|
||||
} else {
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
|
||||
if(GetConsoleScreenBufferInfo(hConsole, &originalSbi) != 0) {
|
||||
defaultForegroundColor = win32ConsoleColorToArsdTerminalColor(originalSbi.wAttributes & 0x0f);
|
||||
defaultBackgroundColor = win32ConsoleColorToArsdTerminalColor((originalSbi.wAttributes >> 4) & 0x0f);
|
||||
} else {
|
||||
// throw new Exception("not a user-interactive terminal");
|
||||
UseWin32Console = false;
|
||||
}
|
||||
|
||||
// this is unnecessary since I use the W versions of other functions
|
||||
// and can cause weird font bugs, so I'm commenting unless some other
|
||||
// need comes up.
|
||||
/*
|
||||
oldCp = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(65001); // UTF-8
|
||||
|
||||
oldCpIn = GetConsoleCP();
|
||||
SetConsoleCP(65001); // UTF-8
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
version(Posix)
|
||||
private void posixInitialize(ConsoleOutputType type, int fdIn = 0, int fdOut = 1, int[] delegate() getSizeOverride = null) {
|
||||
this.fdIn = fdIn;
|
||||
|
@ -1412,7 +1463,14 @@ struct Terminal {
|
|||
}
|
||||
|
||||
private void goCellular() {
|
||||
version(Win32Console) {
|
||||
if(!Terminal.stdoutIsTerminal)
|
||||
throw new Exception("Cannot go to cellular mode with redirected output");
|
||||
|
||||
if(UseVtSequences) {
|
||||
doTermcap("ti");
|
||||
clear();
|
||||
moveTo(0, 0, ForceOption.alwaysSend); // we need to know where the cursor is for some features to work, and moving it is easier than querying it
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, 0, null, CONSOLE_TEXTMODE_BUFFER, null);
|
||||
if(hConsole == INVALID_HANDLE_VALUE) {
|
||||
import std.conv;
|
||||
|
@ -1440,23 +1498,19 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
GetConsoleCursorInfo(hConsole, &originalCursorInfo);
|
||||
|
||||
clear();
|
||||
} else {
|
||||
doTermcap("ti");
|
||||
clear();
|
||||
moveTo(0, 0, ForceOption.alwaysSend); // we need to know where the cursor is for some features to work, and moving it is easier than querying it
|
||||
}
|
||||
}
|
||||
|
||||
private void goLinear() {
|
||||
version(Win32Console) {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("te");
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
auto stdo = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
SetConsoleActiveScreenBuffer(stdo);
|
||||
if(hConsole !is stdo)
|
||||
CloseHandle(hConsole);
|
||||
|
||||
hConsole = stdo;
|
||||
} else {
|
||||
doTermcap("te");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1492,44 +1546,11 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
CONSOLE_SCREEN_BUFFER_INFO originalSbi;
|
||||
}
|
||||
|
||||
version(Win32Console)
|
||||
/// ditto
|
||||
this(ConsoleOutputType type) {
|
||||
_initialized = true;
|
||||
if(UseVtSequences) {
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
initializeVt();
|
||||
} else {
|
||||
if(type == ConsoleOutputType.cellular) {
|
||||
goCellular();
|
||||
} else {
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
|
||||
if(GetConsoleScreenBufferInfo(hConsole, &originalSbi) == 0)
|
||||
throw new Exception("not a user-interactive terminal");
|
||||
|
||||
defaultForegroundColor = cast(Color) (originalSbi.wAttributes & 0x0f);
|
||||
defaultBackgroundColor = cast(Color) ((originalSbi.wAttributes >> 4) & 0x0f);
|
||||
|
||||
// this is unnecessary since I use the W versions of other functions
|
||||
// and can cause weird font bugs, so I'm commenting unless some other
|
||||
// need comes up.
|
||||
/*
|
||||
oldCp = GetConsoleOutputCP();
|
||||
SetConsoleOutputCP(65001); // UTF-8
|
||||
|
||||
oldCpIn = GetConsoleCP();
|
||||
SetConsoleCP(65001); // UTF-8
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
version(Win32Console) {
|
||||
private Color defaultBackgroundColor = Color.black;
|
||||
private Color defaultForegroundColor = Color.white;
|
||||
UINT oldCp;
|
||||
UINT oldCpIn;
|
||||
// UINT oldCp;
|
||||
// UINT oldCpIn;
|
||||
}
|
||||
|
||||
// only use this if you are sure you know what you want, since the terminal is a shared resource you generally really want to reset it to normal when you leave...
|
||||
|
@ -1582,7 +1603,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
if(lineGetter !is null)
|
||||
lineGetter.dispose();
|
||||
} else version(Win32Console) {
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
flush(); // make sure user data is all flushed before resetting
|
||||
reset();
|
||||
showCursor();
|
||||
|
@ -1591,12 +1612,16 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
lineGetter.dispose();
|
||||
|
||||
|
||||
/+
|
||||
SetConsoleOutputCP(oldCp);
|
||||
SetConsoleCP(oldCpIn);
|
||||
+/
|
||||
|
||||
goLinear();
|
||||
}
|
||||
|
||||
flush();
|
||||
|
||||
version(TerminalDirectToEmulator)
|
||||
if(usingDirectEmulator && guiThread !is null) {
|
||||
guiThread.join();
|
||||
|
@ -1647,15 +1672,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
_currentForegroundRGB = foreground;
|
||||
_currentBackgroundRGB = background;
|
||||
|
||||
version(Win32Console) {
|
||||
flush();
|
||||
ushort setTob = cast(ushort) approximate16Color(background);
|
||||
ushort setTof = cast(ushort) approximate16Color(foreground);
|
||||
SetConsoleTextAttribute(
|
||||
hConsole,
|
||||
cast(ushort)((setTob << 4) | setTof));
|
||||
return false;
|
||||
} else {
|
||||
if(UseVtSequences) {
|
||||
// FIXME: if the terminal reliably does support 24 bit color, use it
|
||||
// instead of the round off. But idk how to detect that yet...
|
||||
|
||||
|
@ -1694,13 +1711,55 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
+/
|
||||
|
||||
return true;
|
||||
} version(Win32Console) if(UseWin32Console) {
|
||||
flush();
|
||||
ushort setTob = arsdTerminalColorToWin32ConsoleColor(approximate16Color(background));
|
||||
ushort setTof = arsdTerminalColorToWin32ConsoleColor(approximate16Color(foreground));
|
||||
SetConsoleTextAttribute(
|
||||
hConsole,
|
||||
cast(ushort)((setTob << 4) | setTof));
|
||||
return false;
|
||||
}
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/// Changes the current color. See enum [Color] for the values and note colors can be [arsd.docs.general_concepts#bitmasks|bitwise-or] combined with [Bright].
|
||||
void color(int foreground, int background, ForceOption force = ForceOption.automatic, bool reverseVideo = false) {
|
||||
if(!stdoutIsTerminal)
|
||||
return;
|
||||
if(force != ForceOption.neverSend) {
|
||||
version(Win32Console) {
|
||||
if(UseVtSequences) {
|
||||
import std.process;
|
||||
// I started using this envvar for my text editor, but now use it elsewhere too
|
||||
// if we aren't set to dark, assume light
|
||||
/*
|
||||
if(getenv("ELVISBG") == "dark") {
|
||||
// LowContrast on dark bg menas
|
||||
} else {
|
||||
foreground ^= LowContrast;
|
||||
background ^= LowContrast;
|
||||
}
|
||||
*/
|
||||
|
||||
ushort setTof = cast(ushort) foreground & ~Bright;
|
||||
ushort setTob = cast(ushort) background & ~Bright;
|
||||
|
||||
if(foreground & Color.DEFAULT)
|
||||
setTof = 9; // ansi sequence for reset
|
||||
if(background == Color.DEFAULT)
|
||||
setTob = 9;
|
||||
|
||||
import std.string;
|
||||
|
||||
if(force == ForceOption.alwaysSend || reverseVideo != this.reverseVideo || foreground != _currentForeground || background != _currentBackground) {
|
||||
writeStringRaw(format("\033[%dm\033[3%dm\033[4%dm\033[%dm",
|
||||
(foreground != Color.DEFAULT && (foreground & Bright)) ? 1 : 0,
|
||||
cast(int) setTof,
|
||||
cast(int) setTob,
|
||||
reverseVideo ? 7 : 27
|
||||
));
|
||||
}
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
// assuming a dark background on windows, so LowContrast == dark which means the bit is NOT set on hardware
|
||||
/*
|
||||
foreground ^= LowContrast;
|
||||
|
@ -1731,38 +1790,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
}
|
||||
SetConsoleTextAttribute(
|
||||
hConsole,
|
||||
cast(ushort)((setTob << 4) | setTof));
|
||||
}
|
||||
} else {
|
||||
import std.process;
|
||||
// I started using this envvar for my text editor, but now use it elsewhere too
|
||||
// if we aren't set to dark, assume light
|
||||
/*
|
||||
if(getenv("ELVISBG") == "dark") {
|
||||
// LowContrast on dark bg menas
|
||||
} else {
|
||||
foreground ^= LowContrast;
|
||||
background ^= LowContrast;
|
||||
}
|
||||
*/
|
||||
|
||||
ushort setTof = cast(ushort) foreground & ~Bright;
|
||||
ushort setTob = cast(ushort) background & ~Bright;
|
||||
|
||||
if(foreground & Color.DEFAULT)
|
||||
setTof = 9; // ansi sequence for reset
|
||||
if(background == Color.DEFAULT)
|
||||
setTob = 9;
|
||||
|
||||
import std.string;
|
||||
|
||||
if(force == ForceOption.alwaysSend || reverseVideo != this.reverseVideo || foreground != _currentForeground || background != _currentBackground) {
|
||||
writeStringRaw(format("\033[%dm\033[3%dm\033[4%dm\033[%dm",
|
||||
(foreground != Color.DEFAULT && (foreground & Bright)) ? 1 : 0,
|
||||
cast(int) setTof,
|
||||
cast(int) setTob,
|
||||
reverseVideo ? 7 : 27
|
||||
));
|
||||
cast(ushort)((arsdTerminalColorToWin32ConsoleColor(cast(Color) setTob) << 4) | arsdTerminalColorToWin32ConsoleColor(cast(Color) setTof)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1927,12 +1955,15 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
/// Returns the terminal to normal output colors
|
||||
void reset() {
|
||||
version(Win32Console)
|
||||
SetConsoleTextAttribute(
|
||||
hConsole,
|
||||
originalSbi.wAttributes);
|
||||
else
|
||||
writeStringRaw("\033[0m");
|
||||
if(stdoutIsTerminal) {
|
||||
if(UseVtSequences)
|
||||
writeStringRaw("\033[0m");
|
||||
else version(Win32Console) if(UseWin32Console) {
|
||||
SetConsoleTextAttribute(
|
||||
hConsole,
|
||||
originalSbi.wAttributes);
|
||||
}
|
||||
}
|
||||
|
||||
_underlined = false;
|
||||
_italics = false;
|
||||
|
@ -1974,8 +2005,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
executeAutoHideCursor();
|
||||
if(UseVtSequences) {
|
||||
doTermcap("cm", y, x);
|
||||
} else version(Win32Console) {
|
||||
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
flush(); // if we don't do this now, the buffering can screw up the position
|
||||
COORD coord = {cast(short) x, cast(short) y};
|
||||
SetConsoleCursorPosition(hConsole, coord);
|
||||
|
@ -1990,7 +2020,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
void showCursor() {
|
||||
if(UseVtSequences)
|
||||
doTermcap("ve");
|
||||
else version(Win32Console) {
|
||||
else version(Win32Console) if(UseWin32Console) {
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.bVisible = true;
|
||||
|
@ -2002,7 +2032,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
void hideCursor() {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("vi");
|
||||
} else version(Win32Console) {
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
CONSOLE_CURSOR_INFO info;
|
||||
GetConsoleCursorInfo(hConsole, &info);
|
||||
info.bVisible = false;
|
||||
|
@ -2022,12 +2052,11 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
private void executeAutoHideCursor() {
|
||||
if(autoHidingCursor) {
|
||||
version(Win32Console)
|
||||
hideCursor();
|
||||
else if(UseVtSequences) {
|
||||
if(UseVtSequences) {
|
||||
// prepend the hide cursor command so it is the first thing flushed
|
||||
writeBuffer = "\033[?25l" ~ writeBuffer;
|
||||
}
|
||||
} else version(Win32Console) if(UseWin32Console)
|
||||
hideCursor();
|
||||
|
||||
autoHiddenCursor = true;
|
||||
autoHidingCursor = false; // already been done, don't insert the command again
|
||||
|
@ -2056,7 +2085,10 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
|
||||
/// Changes the terminal's title
|
||||
void setTitle(string t) {
|
||||
version(Win32Console) {
|
||||
import std.string;
|
||||
if(terminalInFamily("xterm", "rxvt", "screen", "tmux"))
|
||||
writeStringRaw(format("\033]0;%s\007", t));
|
||||
else version(Win32Console) if(UseWin32Console) {
|
||||
wchar[256] buffer;
|
||||
size_t bufferLength;
|
||||
foreach(wchar ch; t)
|
||||
|
@ -2067,10 +2099,6 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
else
|
||||
buffer[$-1] = 0;
|
||||
SetConsoleTitleW(buffer.ptr);
|
||||
} else {
|
||||
import std.string;
|
||||
if(terminalInFamily("xterm", "rxvt", "screen", "tmux"))
|
||||
writeStringRaw(format("\033]0;%s\007", t));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2106,6 +2134,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
version(Posix) {
|
||||
if(_writeDelegate !is null) {
|
||||
_writeDelegate(writeBuffer);
|
||||
writeBuffer = null;
|
||||
} else {
|
||||
ssize_t written;
|
||||
|
||||
|
@ -2125,14 +2154,22 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
}
|
||||
}
|
||||
} else version(Win32Console) {
|
||||
import std.conv;
|
||||
// FIXME: I'm not sure I'm actually happy with this allocation but
|
||||
// it probably isn't a big deal. At least it has unicode support now.
|
||||
wstring writeBufferw = to!wstring(writeBuffer);
|
||||
while(writeBufferw.length) {
|
||||
DWORD written;
|
||||
WriteConsoleW(hConsole, writeBufferw.ptr, cast(DWORD)writeBufferw.length, &written, null);
|
||||
writeBufferw = writeBufferw[written .. $];
|
||||
// if(_writeDelegate !is null)
|
||||
// _writeDelegate(writeBuffer);
|
||||
|
||||
if(UseWin32Console) {
|
||||
import std.conv;
|
||||
// FIXME: I'm not sure I'm actually happy with this allocation but
|
||||
// it probably isn't a big deal. At least it has unicode support now.
|
||||
wstring writeBufferw = to!wstring(writeBuffer);
|
||||
while(writeBufferw.length) {
|
||||
DWORD written;
|
||||
WriteConsoleW(hConsole, writeBufferw.ptr, cast(DWORD)writeBufferw.length, &written, null);
|
||||
writeBufferw = writeBufferw[written .. $];
|
||||
}
|
||||
} else {
|
||||
import std.stdio;
|
||||
stdout.rawWrite(writeBuffer); // FIXME
|
||||
}
|
||||
|
||||
writeBuffer = null;
|
||||
|
@ -2151,6 +2188,8 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
}
|
||||
|
||||
private int[] getSizeInternal() {
|
||||
if(!stdoutIsTerminal)
|
||||
throw new Exception("unable to get size of non-terminal");
|
||||
version(Windows) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo( hConsole, &info );
|
||||
|
@ -2350,7 +2389,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
void clear() {
|
||||
if(UseVtSequences) {
|
||||
doTermcap("cl");
|
||||
} else version(Win32Console) {
|
||||
} else version(Win32Console) if(UseWin32Console) {
|
||||
// http://support.microsoft.com/kb/99261
|
||||
flush();
|
||||
|
||||
|
@ -2379,7 +2418,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
if(UseVtSequences) {
|
||||
writeStringRaw("\033[0K");
|
||||
}
|
||||
else version(Windows) {
|
||||
else version(Win32Console) if(UseWin32Console) {
|
||||
updateCursorPosition();
|
||||
auto x = _cursorX;
|
||||
auto y = _cursorY;
|
||||
|
@ -2408,7 +2447,7 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
terminal.writeln(line);
|
||||
---
|
||||
)
|
||||
You really shouldn't call this if stdin isn't actually a user-interactive terminal! So if you expect people to pipe data to your app, check for that or use something else. See [stdinIsTerminal].
|
||||
You really shouldn't call this if stdin isn't actually a user-interactive terminal! However, if it isn't, it will simply read one line from the pipe without writing the prompt. See [stdinIsTerminal].
|
||||
|
||||
Params:
|
||||
prompt = the prompt to give the user. For example, `"Your name: "`.
|
||||
|
@ -2423,8 +2462,16 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
Always pass a string if you want it to display a string.
|
||||
|
||||
The `prefilledData` (and overload with it as second param) was added on January 1, 2023 (dub v10.10 / v11.0).
|
||||
|
||||
On November 7, 2023 (dub v11.3), this function started returning stdin.readln in the event that the instance is not connected to a terminal.
|
||||
+/
|
||||
string getline(string prompt = null, dchar echoChar = dchar.init, string prefilledData = null) {
|
||||
if(!stdoutIsTerminal || !stdinIsTerminal) {
|
||||
import std.stdio;
|
||||
import std.string;
|
||||
return readln().chomp;
|
||||
}
|
||||
|
||||
if(lineGetter is null)
|
||||
lineGetter = new LineGetter(&this);
|
||||
// since the struct might move (it shouldn't, this should be unmovable!) but since
|
||||
|
@ -2500,12 +2547,16 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
|
|||
}
|
||||
}
|
||||
private void updateCursorPosition_impl() {
|
||||
if(!stdinIsTerminal || !stdoutIsTerminal)
|
||||
throw new Exception("cannot update cursor position on non-terminal");
|
||||
auto terminal = &this;
|
||||
version(Win32Console) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(terminal.hConsole, &info);
|
||||
_cursorX = info.dwCursorPosition.X;
|
||||
_cursorY = info.dwCursorPosition.Y;
|
||||
if(UseWin32Console) {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
GetConsoleScreenBufferInfo(terminal.hConsole, &info);
|
||||
_cursorX = info.dwCursorPosition.X;
|
||||
_cursorY = info.dwCursorPosition.Y;
|
||||
}
|
||||
} else version(Posix) {
|
||||
// request current cursor position
|
||||
|
||||
|
@ -4780,6 +4831,8 @@ version(Posix)
|
|||
private uint /* TerminalCapabilities bitmask */ getTerminalCapabilities(int fdIn, int fdOut) {
|
||||
if(fdIn == -1 || fdOut == -1)
|
||||
return TerminalCapabilities.minimal;
|
||||
if(!isatty(fdIn) || !isatty(fdOut))
|
||||
return TerminalCapabilities.minimal;
|
||||
|
||||
import std.conv;
|
||||
import core.stdc.errno;
|
||||
|
@ -8415,15 +8468,37 @@ RGB xtermPaletteIndexToColor(int paletteIdx) {
|
|||
return color;
|
||||
}
|
||||
|
||||
int approximate16Color(RGB color) {
|
||||
Color approximate16Color(RGB color) {
|
||||
int c;
|
||||
c |= color.r > 64 ? RED_BIT : 0;
|
||||
c |= color.g > 64 ? GREEN_BIT : 0;
|
||||
c |= color.b > 64 ? BLUE_BIT : 0;
|
||||
c |= color.r > 64 ? 1 : 0;
|
||||
c |= color.g > 64 ? 2 : 0;
|
||||
c |= color.b > 64 ? 4 : 0;
|
||||
|
||||
c |= (((color.r + color.g + color.b) / 3) > 80) ? Bright : 0;
|
||||
|
||||
return c;
|
||||
return cast(Color) c;
|
||||
}
|
||||
|
||||
Color win32ConsoleColorToArsdTerminalColor(ushort c) {
|
||||
ushort v = cast(ushort) c;
|
||||
auto b1 = v & 1;
|
||||
auto b2 = v & 2;
|
||||
auto b3 = v & 4;
|
||||
auto b4 = v & 8;
|
||||
|
||||
return cast(Color) ((b1 << 2) | b2 | (b3 >> 2) | b4);
|
||||
}
|
||||
|
||||
ushort arsdTerminalColorToWin32ConsoleColor(Color c) {
|
||||
assert(c != Color.DEFAULT);
|
||||
|
||||
ushort v = cast(ushort) c;
|
||||
auto b1 = v & 1;
|
||||
auto b2 = v & 2;
|
||||
auto b3 = v & 4;
|
||||
auto b4 = v & 8;
|
||||
|
||||
return cast(ushort) ((b1 << 2) | b2 | (b3 >> 2) | b4);
|
||||
}
|
||||
|
||||
version(TerminalDirectToEmulator) {
|
||||
|
|
Loading…
Reference in New Issue