Skip to content

Commit 95d5354

Browse files
committed
FEAT: added possibility to change console output from stdout to stderr (windows)
related to: Oldes/Rebol-issues#1862 Oldes/Rebol-issues#2468
1 parent 9c40364 commit 95d5354

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

src/os/win32/dev-stdio.c

+17-11
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
| ENABLE_EXTENDED_FLAGS | ENABLE_QUICK_EDIT_MODE | ENABLE_INSERT_MODE
7575

7676
static HANDLE Std_Out = 0;
77+
static HANDLE Std_Err = 0;
7778
static HANDLE Std_Inp = 0;
7879
static HANDLE Std_Echo = 0;
7980
static REBCHR *Std_Buf = 0; // for input and output
@@ -426,13 +427,14 @@ static void Close_StdIO_Local(void)
426427
const REBYTE *bp;
427428
const REBYTE *cp;
428429
const REBYTE *ep;
430+
HANDLE hOutput = Std_Err ? Std_Err : Std_Out;
429431

430432
if (GET_FLAG(req->modes, RDM_NULL)) {
431433
req->actual = req->length;
432434
return DR_DONE;
433435
}
434436

435-
if (Std_Out) {
437+
if (hOutput) {
436438

437439
bp = req->data;
438440
ep = bp + req->length;
@@ -447,11 +449,11 @@ static void Close_StdIO_Local(void)
447449

448450
if (Redir_Out) { // for Console SubSystem (always UTF-8)
449451
if (cp) {
450-
ok = WriteFile(Std_Out, bp, cp - bp, &total, 0);
452+
ok = WriteFile(hOutput, bp, cp - bp, &total, 0);
451453
bp = Parse_ANSI_sequence(cp, ep);
452454
}
453455
else {
454-
ok = WriteFile(Std_Out, bp, ep - bp, &total, 0);
456+
ok = WriteFile(hOutput, bp, ep - bp, &total, 0);
455457
bp = ep;
456458
}
457459
if (!ok) {
@@ -469,7 +471,7 @@ static void Close_StdIO_Local(void)
469471
bp = ep;
470472
}
471473
if (len > 0) {// no error
472-
ok = WriteConsoleW(Std_Out, Std_Buf, len, &total, 0);
474+
ok = WriteConsoleW(hOutput, Std_Buf, len, &total, 0);
473475
if (!ok) {
474476
req->error = GetLastError();
475477
return DR_ERROR;
@@ -484,7 +486,7 @@ static void Close_StdIO_Local(void)
484486
} else {
485487
// using MS built in ANSI processing
486488
if (Redir_Out) { // Always UTF-8
487-
ok = WriteFile(Std_Out, req->data, req->length, &total, 0);
489+
ok = WriteFile(hOutput, req->data, req->length, &total, 0);
488490
}
489491
else {
490492
// Convert UTF-8 buffer to Win32 wide-char format for console.
@@ -494,7 +496,7 @@ static void Close_StdIO_Local(void)
494496
// because its UTF-8 with variable char sizes.
495497
len = MultiByteToWideChar(CP_UTF8, 0, cs_cast(req->data), req->length, Std_Buf, BUF_SIZE);
496498
if (len > 0) // no error
497-
ok = WriteConsoleW(Std_Out, Std_Buf, len, &total, 0);
499+
ok = WriteConsoleW(hOutput, Std_Buf, len, &total, 0);
498500
}
499501
}
500502
req->actual = req->length; // do not use "total" (can be byte or wide)
@@ -550,9 +552,10 @@ static void Close_StdIO_Local(void)
550552
// CTRL-C pressed
551553
Handled_Break = TRUE; // let the break handler (which is signaled later) to know,
552554
// that we handled it already
553-
SetConsoleTextAttribute(Std_Out, FOREGROUND_INTENSITY | FOREGROUND_MAGENTA);
554-
WriteConsoleW(Std_Out, L"[ESC]\r\n", 7, NULL, 0);
555-
SetConsoleTextAttribute(Std_Out, FOREGROUND_GREY);
555+
HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE);
556+
SetConsoleTextAttribute(hErr, FOREGROUND_INTENSITY | FOREGROUND_MAGENTA);
557+
WriteConsoleW(hErr, L"[ESC]\r\n", 7, NULL, 0);
558+
SetConsoleTextAttribute(hErr, FOREGROUND_GREY);
556559
req->data[0] = '\x1B'; // ESC char
557560
req->actual = 1;
558561
return DR_DONE;
@@ -600,7 +603,7 @@ static void Close_StdIO_Local(void)
600603
REBEVT evt;
601604
DWORD cNumRead, i, repeat;
602605
INPUT_RECORD irInBuf[8];
603-
if (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE), irInBuf, 8, &cNumRead)) {
606+
if (ReadConsoleInput(Std_Inp, irInBuf, 8, &cNumRead)) {
604607
//printf("cNumRead: %u\n", cNumRead);
605608
for (i = 0; i < cNumRead; i++)
606609
{
@@ -732,7 +735,7 @@ static void Close_StdIO_Local(void)
732735
case MODE_CONSOLE_LINE:
733736
Set_Input_Mode(ENABLE_LINE_INPUT | ENABLE_QUICK_EDIT_MODE | ENABLE_PROCESSED_INPUT, value);
734737
Set_Input_Mode(ENABLE_MOUSE_INPUT, !value);
735-
if(req->modify.value) {
738+
if (value) {
736739
SET_FLAG(req->modes, RDM_READ_LINE);
737740
}
738741
else {
@@ -741,6 +744,9 @@ static void Close_StdIO_Local(void)
741744
SET_FLAG(Devices[1]->flags, RDO_AUTO_POLL);
742745
}
743746
break;
747+
case MODE_CONSOLE_ERROR:
748+
Std_Err = value ? GetStdHandle(STD_ERROR_HANDLE) : 0;
749+
break;
744750
}
745751
return DR_DONE;
746752
}

src/tests/units/call-test.r3

+15-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ Rebol [
99
~~~start-file~~~ "CALL"
1010

1111
out-buffer: copy ""
12+
err-buffer: copy ""
1213

1314
rebol-cmd: func[cmd][
1415
clear out-buffer
16+
clear err-buffer
1517
insert cmd join to-local-file system/options/boot #" "
16-
call/shell/wait/output cmd out-buffer
18+
call/shell/wait/output/error cmd out-buffer err-buffer
1719
]
1820

1921
===start-group=== "Command-Line Interface"
@@ -60,4 +62,16 @@ rebol-cmd: func[cmd][
6062
]
6163
===end-group===
6264

65+
66+
===start-group=== "Error pipe"
67+
--test-- "User controlled error output"
68+
;@@ https://github.com/Oldes/Rebol-issues/issues/2468
69+
; the port should be renamed from `input` to `io` or `console`, because it is not just an input!!
70+
--assert 0 = rebol-cmd {--do "prin 1 modify system/ports/input 'error on prin 2 modify system/ports/input 'error off prin 3}
71+
--assert "13" = out-buffer
72+
--assert "2" = err-buffer
73+
74+
75+
===end-group===
76+
6377
~~~end-file~~~

0 commit comments

Comments
 (0)