Check output device is a terminal: Difference between revisions

From Rosetta Code
Content added Content deleted
imported>Regattaguru
 
(15 intermediate revisions by 9 users not shown)
Line 1: Line 1:
[[Category:Hardware]]
[[Category:Terminal control]]
[[Category:Initialization]]
{{task}}
{{task}}
[[Category:Hardware]]
[[Category:Terminal control]]
[[Category:Initialization]]
{{omit from|TI-83 BASIC|Output device is always either a terminal or created by the program}}


;Task:
;Task:
Line 12: Line 13:
*   [[Check input device is a terminal]]
*   [[Check input device is a terminal]]
<br><br>
<br><br>
=={{header|6502 Assembly}}==

{{works with|Commodore 64}}
<syntaxhighlight lang="6502asm">LDA $D011 ;screen control register 1
AND #%00100000 ;bit 5 clear = text mode, bit 5 set = gfx mode
BEQ isTerminal</syntaxhighlight>
=={{header|Ada}}==
=={{header|Ada}}==
{{works with|GNAT}}
{{works with|GNAT}}
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>.
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>.


<lang ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C_Streams; use Interfaces.C_Streams;
with Interfaces.C_Streams; use Interfaces.C_Streams;


Line 27: Line 32:
Put_Line(Standard_Error, "stdout is a tty.");
Put_Line(Standard_Error, "stdout is a tty.");
end if;
end if;
end Test_tty;</lang>
end Test_tty;</syntaxhighlight>


{{out}}
{{out}}
Line 37: Line 42:
stdout is not a tty.
stdout is not a tty.
</pre>
</pre>

=={{header|C}}==
=={{header|C}}==


Use <code>isatty()</code> on file descriptor to determine if it's a TTY. To get the file descriptor from a <code>FILE*</code> pointer, use <code>fileno</code>:
Use <code>isatty()</code> on file descriptor to determine if it's a TTY. To get the file descriptor from a <code>FILE*</code> pointer, use <code>fileno</code>:


<lang c>#include <unistd.h> // for isatty()
<syntaxhighlight lang="c">#include <unistd.h> // for isatty()
#include <stdio.h> // for fileno()
#include <stdio.h> // for fileno()


Line 51: Line 55:
: "stdout is not tty");
: "stdout is not tty");
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 66: Line 70:
stdout is not tty
stdout is not tty
</pre>
</pre>

=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


namespace CheckTerminal {
namespace CheckTerminal {
Line 76: Line 79:
}
}
}
}
}</lang>
}</syntaxhighlight>

=={{header|C++}}==
=={{header|C++}}==
{{trans|C}}
{{trans|C}}
<lang cpp>#if _WIN32
<syntaxhighlight lang="cpp">#if _WIN32
#include <io.h>
#include <io.h>
#define ISATTY _isatty
#define ISATTY _isatty
Line 100: Line 102:


return 0;
return 0;
}</lang>
}</syntaxhighlight>

=={{header|COBOL}}==
=={{header|COBOL}}==
Works with GnuCOBOL.
Works with GnuCOBOL.


<lang cobol> *>
<syntaxhighlight lang="cobol"> *>
*> istty, check id fd 0 is a tty
*> istty, check id fd 0 is a tty
*> Tectonics: cobc -xj istty.cob
*> Tectonics: cobc -xj istty.cob
Line 130: Line 131:


goback.
goback.
end program istty.</lang>
end program istty.</syntaxhighlight>


DISPLAY for fd 1 is directed to SYSERR to get some output during the various trials.
DISPLAY for fd 1 is directed to SYSERR to get some output during the various trials.
Line 152: Line 153:
fd 0 tty: +0000000000
fd 0 tty: +0000000000
fd 2 tty: +0000000000</pre>
fd 2 tty: +0000000000</pre>

=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
{{Works with|SBCL}}
{{Works with|SBCL}}
<lang lisp>(with-open-stream (s *standard-output*)
<syntaxhighlight lang="lisp">(with-open-stream (s *standard-output*)
(format T "stdout is~:[ not~;~] a terminal~%"
(format T "stdout is~:[ not~;~] a terminal~%"
(interactive-stream-p s)))</lang>
(interactive-stream-p s)))</syntaxhighlight>


{{Out}}
{{Out}}
Line 171: Line 171:
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>. It needs to be compiled to be executed.
We use the interface to C library functions <code>isatty()</code> and <code>fileno()</code>. It needs to be compiled to be executed.


<lang lisp>(ffi:clines "
<syntaxhighlight lang="lisp">(ffi:clines "
#include <sys/ioctl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <unistd.h>
Line 188: Line 188:


(format T "stdout is~:[ not~;~] a terminal~%" (tty-p))
(format T "stdout is~:[ not~;~] a terminal~%" (tty-p))
(quit)</lang>
(quit)</syntaxhighlight>


Compilation can be done with the following commands :
Compilation can be done with the following commands :
Line 201: Line 201:
$ ./is-tty | cat -
$ ./is-tty | cat -
stdout is not a terminal</pre>
stdout is not a terminal</pre>

=={{header|Crystal}}==
=={{header|Crystal}}==
<lang ruby>File.new("testfile").tty? #=> false
<syntaxhighlight lang="ruby">File.new("testfile").tty? #=> false
File.new("/dev/tty").tty? #=> true
File.new("/dev/tty").tty? #=> true
STDOUT.tty? #=> true</lang>
STDOUT.tty? #=> true</syntaxhighlight>

=={{header|D}}==
=={{header|D}}==
<lang D>import std.stdio;
<syntaxhighlight lang="d">import std.stdio;


extern(C) int isatty(int);
extern(C) int isatty(int);
Line 214: Line 212:
void main() {
void main() {
writeln("Stdout is tty: ", stdout.fileno.isatty == 1);
writeln("Stdout is tty: ", stdout.fileno.isatty == 1);
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 223: Line 221:
Stdout is tty: false
Stdout is tty: false
</pre>
</pre>

=={{header|Factor}}==
=={{header|Factor}}==
You have to know 1 is the correct file descriptor number:
You have to know 1 is the correct file descriptor number:
<lang factor>
<syntaxhighlight lang="factor">
IN: scratchpad USE: unix.ffi
IN: scratchpad USE: unix.ffi
IN: scratchpad 1 isatty
IN: scratchpad 1 isatty
Line 232: Line 229:
--- Data stack:
--- Data stack:
1
1
</syntaxhighlight>
</lang>
=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
Open Cons For Output As #1
' Open Cons abre los flujos de entrada (stdin) o salida (stdout) estándar
' de la consola para leer o escribir.


If Err > 0 Then
Print #1, "stdout is not a tty."
Else
Print #1, "stdout is a tty."
End If
Close #1
Sleep
</syntaxhighlight>
=={{header|Go}}==
=={{header|Go}}==
Tells a ''terminal'' apart from a ''pipe'' on Linux and Mac, which is probably exactly what you need.
Tells a ''terminal'' apart from a ''pipe'' on Linux and Mac, which is probably exactly what you need.


<lang go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 250: Line 260:
fmt.Println("Who are you? You're not a terminal")
fmt.Println("Who are you? You're not a terminal")
}
}
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 258: Line 268:
Who are you? You're not a terminal.
Who are you? You're not a terminal.
</pre>
</pre>

=={{header|Haskell}}==
=={{header|Haskell}}==


<lang haskell>module Main where
<syntaxhighlight lang="haskell">module Main where


-- requires the unix package
-- requires the unix package
Line 274: Line 283:
(if istty
(if istty
then "stdout is tty"
then "stdout is tty"
else "stdout is not tty")</lang>
else "stdout is not tty")</syntaxhighlight>
{{Out}}
{{Out}}
<pre>$ runhaskell istty.hs
<pre>$ runhaskell istty.hs
Line 281: Line 290:
stdout is not tty
stdout is not tty
</pre>
</pre>

=={{header|J}}==
=={{header|J}}==


<lang J>3=nc<'wd'</lang>
<syntaxhighlight lang="j">3=nc<'wd'</syntaxhighlight>


Explanation:
Explanation:
Line 297: Line 305:


But, correctness requires us to keep in mind that these will only be heuristics, and will sometimes be incorrect (hopefully not often enough to matter a lot...).
But, correctness requires us to keep in mind that these will only be heuristics, and will sometimes be incorrect (hopefully not often enough to matter a lot...).

=={{header|Javascript/NodeJS}}==
=={{header|Javascript/NodeJS}}==
<lang js>node -p -e "Boolean(process.stdout.isTTY)"
<syntaxhighlight lang="js">node -p -e "Boolean(process.stdout.isTTY)"
true</lang>
true</syntaxhighlight>

=={{header|Julia}}==
=={{header|Julia}}==
<syntaxhighlight lang="julia">
<lang Julia>
if isa(STDOUT, Base.TTY)
if isa(STDOUT, Base.TTY)
println("This program sees STDOUT as a TTY.")
println("This program sees STDOUT as a TTY.")
Line 309: Line 315:
println("This program does not see STDOUT as a TTY.")
println("This program does not see STDOUT as a TTY.")
end
end
</syntaxhighlight>
</lang>


{{out}}
{{out}}
Line 315: Line 321:
This program sees STDOUT as a TTY.
This program sees STDOUT as a TTY.
</pre>
</pre>

=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{Works with|Ubuntu|14.04}}
{{Works with|Ubuntu|14.04}}
<lang scala>// Kotlin Native version 0.5
<syntaxhighlight lang="scala">// Kotlin Native version 0.5


import platform.posix.*
import platform.posix.*
Line 327: Line 332:
else
else
println("stdout is not a terminal")
println("stdout is not a terminal")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 333: Line 338:
stdout is a terminal
stdout is a terminal
</pre>
</pre>

=={{header|Lua}}==
=={{header|Lua}}==
{{works with|Lua|5.1+}}
{{works with|Lua|5.1+}}
Using pure Lua, assuming a *NIX-like runtime environment ...
Using pure Lua, assuming a *NIX-like runtime environment ...
<lang Lua>local function isTTY ( fd )
<syntaxhighlight lang="lua">local function isTTY ( fd )
fd = tonumber( fd ) or 1
fd = tonumber( fd ) or 1
local ok, exit, signal = os.execute( string.format( "test -t %d", fd ) )
local ok, exit, signal = os.execute( string.format( "test -t %d", fd ) )
Line 345: Line 349:
print( "stdin", isTTY( 0 ) )
print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )</lang>
print( "stderr", isTTY( 2 ) )</syntaxhighlight>


{{out}}
{{out}}
Line 371: Line 375:


You can accomplish the same results using the luaposix [https://github.com/luaposix/luaposix] library:
You can accomplish the same results using the luaposix [https://github.com/luaposix/luaposix] library:
<lang lua>local unistd = require( "posix.unistd" )
<syntaxhighlight lang="lua">local unistd = require( "posix.unistd" )


local function isTTY ( fd )
local function isTTY ( fd )
Line 381: Line 385:
print( "stdin", isTTY( 0 ) )
print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )</lang>
print( "stderr", isTTY( 2 ) )</syntaxhighlight>


The output of this version is identical to the output of the first version.
The output of this version is identical to the output of the first version.

=={{header|Nemerle}}==
=={{header|Nemerle}}==
There is no explicit way (ie <tt>isatty()</tt>)to do this; however, if we ''assume'' that standard out ''is'' a terminal, we can check if the output stream has been redirected (presumably to something other than a terminal).
There is no explicit way (ie <tt>isatty()</tt>)to do this; however, if we ''assume'' that standard out ''is'' a terminal, we can check if the output stream has been redirected (presumably to something other than a terminal).
<lang Nemerle>def isTerm = System.Console.IsOutputRedirected;</lang>
<syntaxhighlight lang="nemerle">def isTerm = System.Console.IsOutputRedirected;</syntaxhighlight>

=={{header|Nim}}==
=={{header|Nim}}==
Using function "isatty" of standard module "terminal" which accepts a File as argument.
Using function "isatty" of standard module "terminal" which accepts a File as argument.
As we want to redirect stdout, we write the messages on stderr.
As we want to redirect stdout, we write the messages on stderr.


<lang Nim>import terminal
<syntaxhighlight lang="nim">import terminal


stderr.write if stdout.isatty: "stdout is a terminal\n" else: "stdout is not a terminal\n"</lang>
stderr.write if stdout.isatty: "stdout is a terminal\n" else: "stdout is not a terminal\n"</syntaxhighlight>


{{out}}
{{out}}
Line 403: Line 405:
<pre>Command: ./check_output_dev >somefile
<pre>Command: ./check_output_dev >somefile
Result: stdout is not a terminal</pre>
Result: stdout is not a terminal</pre>

=={{header|OCaml}}==
=={{header|OCaml}}==


<lang ocaml>let () =
<syntaxhighlight lang="ocaml">let () =
print_endline (
print_endline (
if Unix.isatty Unix.stdout
if Unix.isatty Unix.stdout
then "Output goes to tty."
then "Output goes to tty."
else "Output doesn't go to tty."
else "Output doesn't go to tty."
)</lang>
)</syntaxhighlight>


Testing in interpreted mode:
Testing in interpreted mode:
Line 425: Line 426:
Output doesn't go to tty.
Output doesn't go to tty.
</pre>
</pre>
=={{header|Ol}}==

<syntaxhighlight lang="scheme">
(define (isatty? fd) (syscall 16 fd 19))
(print (if (isatty? stdout)
"stdout is a tty."
"stdout is not a tty."))
</syntaxhighlight>
=={{header|Perl}}==
=={{header|Perl}}==
The -t function on a filehandle tells you whether it's a terminal.
The -t function on a filehandle tells you whether it's a terminal.


<lang bash>$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'"
<syntaxhighlight lang="bash">$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'"
Terminal
Terminal
$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'" > x.tmp
$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'" > x.tmp
Other
Other
</syntaxhighlight>
</lang>

=={{header|Phix}}==
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(notonline)-->
Requires 0.8.2+
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (no input or output redirection in a browser!)</span>
<lang Phix>printf(1,"stdin:%t, stdout:%t, stderr:%t\n",{isatty(0),isatty(1),isatty(2)})</lang>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"stdin:%t, stdout:%t, stderr:%t\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">),</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">isatty</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)})</span>
<!--</syntaxhighlight>-->
{{out}}
{{out}}
<pre>
<pre>
Line 452: Line 460:
stdin:false, stdout:true, stderr:true
stdin:false, stdout:true, stderr:true
</pre>
</pre>

=={{header|PHP}}==
=={{header|PHP}}==
<lang php>
<syntaxhighlight lang="php">
if(posix_isatty(STDOUT)) {
if(posix_isatty(STDOUT)) {
echo "The output device is a terminal".PHP_EOL;
echo "The output device is a terminal".PHP_EOL;
Line 460: Line 467:
echo "The output device is NOT a terminal".PHP_EOL;
echo "The output device is NOT a terminal".PHP_EOL;
}
}
</syntaxhighlight>
</lang>

=={{header|Python}}==
=={{header|Python}}==
Pretty much the same as [[Check input device is a terminal#Python]].
Pretty much the same as [[Check input device is a terminal#Python]].
<lang python>from sys import stdout
<syntaxhighlight lang="python">from sys import stdout
if stdout.isatty():
if stdout.isatty():
print 'The output device is a teletype. Or something like a teletype.'
print 'The output device is a teletype. Or something like a teletype.'
else:
else:
print 'The output device isn\'t like a teletype.'</lang>
print 'The output device isn\'t like a teletype.'</syntaxhighlight>
=={{header|Quackery}}==


{{trans|Python}}

<syntaxhighlight lang="quackery"> [ $ |from sys import stdout
to_stack( 1 if stdout.isatty() else 0)|
python ] is ttyout ( --> b )

ttyout if
[ say "Looks like a teletype." ]
else
[ say "Not a teletype." ]</syntaxhighlight>

{{out}}

<pre>Looks like a teletype.</pre>
=={{header|Racket}}==
=={{header|Racket}}==
<lang racket>
<syntaxhighlight lang="racket">
(terminal-port? (current-output-port))
(terminal-port? (current-output-port))
</syntaxhighlight>
</lang>

=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
Line 483: Line 503:
$ raku -e 'note $*OUT.t' >/dev/null
$ raku -e 'note $*OUT.t' >/dev/null
False</pre>
False</pre>

=={{header|REXX}}==
=={{header|REXX}}==
{{works with|PC/REXX under DOS or in a DOS window under MS Windows}}
{{works with|PC/REXX under DOS or in a DOS window under MS Windows}}
{{works with|Personal REXX under DOS or in a DOS window under MS Windows}}
{{works with|Personal REXX under DOS or in a DOS window under MS Windows}}
{{works with|Regina in a DOS window under MS Windows}}
{{works with|Regina in a DOS window under MS Windows}}


Programming note: &nbsp; The comment about the REXX statements have to be on one line isn't quite true,
Programming note: &nbsp; The comment about the REXX statements have to be on one line isn't quite true,
<br>but because the REXX special variable '''SIGL''' is defined where it's executed, it makes coding simpler.
<br>but because the REXX special variable '''SIGL''' is defined where it's executed, it makes coding simpler.

<br><br>'''SIGL''' &nbsp; is set to the REXX statment number where:

'''SIGL''' &nbsp; is set to the REXX statement number where:
:::* &nbsp; a '''CALL''' statement is used
:::* &nbsp; a '''CALL''' statement is used
:::* &nbsp; a ''function'' is invoked
:::* &nbsp; a ''function'' is invoked
:::* &nbsp; a '''SIGNAL''' statement is used
:::* &nbsp; a '''SIGNAL''' statement is used

Method used: &nbsp; since REXX has no direct way of determining if the STDIN is a terminal or not, the REXX code (below)
Method used: &nbsp; since REXX has no direct way of determining if the STDIN is a terminal or not, the REXX code (below)
<br>actually ''raises'' (which is no way to run a railroad) a syntax error when attempting to read the 2<sup>nd</sup> line from &nbsp; STDIN,
<br>actually &nbsp; ''raises'' &nbsp; (which is no way to run a railroad) &nbsp; a syntax error when attempting to read the 2<sup>nd</sup> line from &nbsp; STDIN,
<br>which causes a routine (named '''syntax:''') to get control, determines where the syntax error occurred, and returns an
<br>which causes a routine &nbsp; (named '''syntax:''') &nbsp; to get control, &nbsp; determines where the syntax error occurred, &nbsp; and returns
<br>appropriate string indicating if STDIN is a '''terminal''' (or '''other''').
<br>an appropriate string indicating if STDIN is a '''terminal''' &nbsp; (or '''other''').
<br><br>Note that under VM/CMS, this can be accomplished with a (host) command within REXX and then examining the results.
<br><br>Note that under VM/CMS, this can be accomplished with a (host) command within REXX and then examining the results.
<br>On IBM mainframes, a user can have STDIN defined, but the terminal can be ''disconnected''.
<br>On IBM mainframes, a user can have STDIN defined, but the terminal can be ''disconnected''.
<lang rexx>/*REXX program determines if the STDIN is a terminal or other. */
signal on syntax /*if syntax error, jump──► SYNTAX*/
say 'output device:' testSTDIN() /*displays terminal ──or── other */
exit /*stick a fork in it, we're done.*/
/*──────────────────────────────────TESTSTDIN subroutine────────────────*/
testSTDIN: syntax.=1; signal .; .: z.=sigl; call linein ,2; ..: syntax.=0
return z.. /* [↑] must all be on one line.*/
/*──────────────────────────────────SYNTAX subroutine───────────────────*/
syntax: z..='other' /*when SYNTAX occur, come here. */
if syntax. then do /*handling STDIN thingy error? */
if sigl==z. then z..='terminal'; signal .. /*stdin ?*/
end /* [↑] can't use a RETURN here.*/


<syntaxhighlight lang="rexx">/*REXX program determines if the STDIN is a terminal device or other. */
/* ··· handle other REXX syntax errors here ··· */</lang>
signal on syntax /*if syntax error, then jump ──► SYNTAX*/
'''output'''
say 'output device:' testSTDIN() /*displays terminal ──or── other */
exit 0 /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
testSTDIN: syntax.=1; signal .; .: z.= sigl; call linein ,2; ..: syntax.= 0; return z..
/* [↑] must/should be all on one line.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
syntax: z..= 'other' /*when a SYNTAX error occurs, come here*/
if syntax. then do /*are we handling STDIN thingy error?*/
if sigl==z. then z..= 'terminal'; signal .. /*is this a stdin ?*/
end /* [↑] can't use a RETURN here. */

/* ··· handle other REXX syntax errors here ··· */</syntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
<pre>
output device: terminal
output device: terminal
</pre>
</pre>





{{works with|R4 REXX under DOS or in a DOS window under MS Windows}}


The following is the output when used with '''R4''' REXX:

{{out|output|text=&nbsp; when using the default input:}}
<pre>
Reading console input (Press Ctrl-Z to quit):
◄■■■■■■■■ user input (pressed ENTER)
◄■■■■■■■■ user input (pressed ENTER a 2nd time)
output device: 6
</pre>
=={{header|Ruby}}==
=={{header|Ruby}}==
<lang rust>f = File.open("test.txt")
<syntaxhighlight lang="rust">f = File.open("test.txt")
p f.isatty # => false
p f.isatty # => false
p STDOUT.isatty # => true
p STDOUT.isatty # => true
</syntaxhighlight>
</lang>

=={{header|Rust}}==
=={{header|Rust}}==
<lang rust>/* Uses C library interface */
<syntaxhighlight lang="rust">/* Uses C library interface */


extern crate libc;
extern crate libc;
Line 537: Line 576:
println!("stdout is not tty");
println!("stdout is not tty");
}
}
}</lang>
}</syntaxhighlight>

=={{header|Scala}}==
=={{header|Scala}}==
{{Works with|Ubuntu|14.04}}
{{Works with|Ubuntu|14.04}}
<lang scala>import org.fusesource.jansi.internal.CLibrary._
<syntaxhighlight lang="scala">import org.fusesource.jansi.internal.CLibrary._


object IsATty extends App {
object IsATty extends App {
Line 561: Line 599:


println("tty " + apply(true))
println("tty " + apply(true))
}</lang>
}</syntaxhighlight>
=={{header|Standard ML}}==
<syntaxhighlight lang="sml">val stdoutRefersToTerminal : bool = Posix.ProcEnv.isatty Posix.FileSys.stdout</syntaxhighlight>
=={{header|Swift}}==
<syntaxhighlight lang="swift">print(isatty(STDOUT_FILENO) != 0 ? "TTY" : "Not TTY" )</syntaxhighlight>


=={{header|Tcl}}==
=={{header|Tcl}}==
To detect whether output is going to a terminal in Tcl, you check whether the <code>stdout</code> channel looks like a serial line (as those are indistinguishable from terminals). The simplest way of doing that is to see whether you can read the <tt>-mode</tt> or <code>-xchar</code> channel options, which are only present on serial channels:
To detect whether output is going to a terminal in Tcl, you check whether the <code>stdout</code> channel looks like a serial line (as those are indistinguishable from terminals). The simplest way of doing that is to see whether you can read the <tt>-mode</tt> or <code>-xchar</code> channel options, which are only present on serial channels:
<lang tcl>set toTTY [dict exists [fconfigure stdout] -mode]
<syntaxhighlight lang="tcl">set toTTY [dict exists [fconfigure stdout] -mode]
puts [expr {$toTTY ? "Output goes to tty" : "Output doesn't go to tty"}]</lang>
puts [expr {$toTTY ? "Output goes to tty" : "Output doesn't go to tty"}]</syntaxhighlight>
At the system call level, when Tcl is setting up the channels that correspond to the underlying <tt>stdout</tt> (and <tt>stdin</tt> and <tt>stderr</tt>) file descriptors, it checks whether the channels are network sockets (with <code>getsockname()</code>) or serial lines (with <code>isatty()</code>). This allows Tcl scripts to find out information about their calling environment (e.g., when they are run from <tt>inetd</tt>) with minimal code.
At the system call level, when Tcl is setting up the channels that correspond to the underlying <tt>stdout</tt> (and <tt>stdin</tt> and <tt>stderr</tt>) file descriptors, it checks whether the channels are network sockets (with <code>getsockname()</code>) or serial lines (with <code>isatty()</code>). This allows Tcl scripts to find out information about their calling environment (e.g., when they are run from <tt>inetd</tt>) with minimal code.
{{out|Demonstrating}}
{{out|Demonstrating}}
Line 576: Line 618:
===Channel type discovery with older Tcl versions===
===Channel type discovery with older Tcl versions===
Before Tcl 8.4, this discovery process is impossible; <code>stdout</code> always looks like it is going to a file. With 8.4, you can discover the channel type but you need slightly different (and less efficient, due to the thrown error in the non-tty case) code to do it.
Before Tcl 8.4, this discovery process is impossible; <code>stdout</code> always looks like it is going to a file. With 8.4, you can discover the channel type but you need slightly different (and less efficient, due to the thrown error in the non-tty case) code to do it.
<lang tcl>set toTTY [expr {![catch {fconfigure stdout -mode}]}]</lang>
<syntaxhighlight lang="tcl">set toTTY [expr {![catch {fconfigure stdout -mode}]}]</syntaxhighlight>

=={{header|UNIX Shell}}==
=={{header|UNIX Shell}}==
<lang sh>#!/bin/sh
<syntaxhighlight lang="sh">#!/bin/sh


if [ -t 1 ]
if [ -t 1 ]
Line 586: Line 627:
else
else
echo "Output is NOT a terminal" >/dev/tty
echo "Output is NOT a terminal" >/dev/tty
fi</lang>
fi</syntaxhighlight>

=={{header|Visual Basic .NET}}==
=={{header|Visual Basic .NET}}==
{{trans|C#}}
{{trans|C#}}
<lang vbnet>Module Module1
<syntaxhighlight lang="vbnet">Module Module1


Sub Main()
Sub Main()
Line 596: Line 636:
End Sub
End Sub


End Module</lang>
End Module</syntaxhighlight>
=={{header|Wren}}==
{{trans|C}}
As there is currently no way to obtain this information via Wren CLI, we instead embed a Wren script in a C application and ask the host program to get it for us.
<syntaxhighlight lang="wren">/* Check_output_device_is_a_terminal.wren */

class C {
foreign static isOutputDeviceTerminal
}

System.print("Output device is a terminal = %(C.isOutputDeviceTerminal)")</syntaxhighlight>
<br>
We now embed this Wren script in the following C program, compile and run it.
<syntaxhighlight lang="c">#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "wren.h"

void C_isOutputDeviceTerminal(WrenVM* vm) {
bool isTerminal = (bool)isatty(fileno(stdout));
wrenSetSlotBool(vm, 0, isTerminal);
}

WrenForeignMethodFn bindForeignMethod(
WrenVM* vm,
const char* module,
const char* className,
bool isStatic,
const char* signature) {
if (strcmp(module, "main") == 0) {
if (strcmp(className, "C") == 0) {
if (isStatic && strcmp(signature, "isOutputDeviceTerminal") == 0) {
return C_isOutputDeviceTerminal;
}
}
}
return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
printf("%s", text);
}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
switch (errorType) {
case WREN_ERROR_COMPILE:
printf("[%s line %d] [Error] %s\n", module, line, msg);
break;
case WREN_ERROR_STACK_TRACE:
printf("[%s line %d] in %s\n", module, line, msg);
break;
case WREN_ERROR_RUNTIME:
printf("[Runtime Error] %s\n", msg);
break;
}
}

char *readFile(const char *fileName) {
FILE *f = fopen(fileName, "r");
fseek(f, 0, SEEK_END);
long fsize = ftell(f);
rewind(f);
char *script = malloc(fsize + 1);
fread(script, 1, fsize, f);
fclose(f);
script[fsize] = 0;
return script;
}

int main() {
WrenConfiguration config;
wrenInitConfiguration(&config);
config.writeFn = &writeFn;
config.errorFn = &errorFn;
config.bindForeignMethodFn = &bindForeignMethod;
WrenVM* vm = wrenNewVM(&config);
const char* module = "main";
const char* fileName = "Check_output_device_is_a_terminal.wren";
char *script = readFile(fileName);
WrenInterpretResult result = wrenInterpret(vm, module, script);
switch (result) {
case WREN_RESULT_COMPILE_ERROR:
printf("Compile Error!\n");
break;
case WREN_RESULT_RUNTIME_ERROR:
printf("Runtime Error!\n");
break;
case WREN_RESULT_SUCCESS:
break;
}
wrenFreeVM(vm);
free(script);
return 0;
}</syntaxhighlight>

{{out}}
<pre>
$ ./Check_output_device_is_a_terminal
Output device is a terminal = true

$ ./Check_output_device_is_a_terminal > tmp
$ cat tmp
Output device is a terminal = false

$ ./Check_output_device_is_a_terminal | cat
Output device is a terminal = false
</pre>


=={{header|zkl}}==
=={{header|zkl}}==
On Unix, check to see if stdout's st_mode is a character device.
On Unix, check to see if stdout's st_mode is a character device.
<lang zkl>const S_IFCHR=0x2000;
<syntaxhighlight lang="zkl">const S_IFCHR=0x2000;
fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() }
fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() }
S_ISCHR(File.stdout).println();</lang>
S_ISCHR(File.stdout).println();</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 613: Line 760:
False
False
</pre>
</pre>
{{omit from|TI-83 BASIC|Output device is always either a terminal or created by the program}}

Latest revision as of 12:27, 15 February 2024

Task
Check output device is a terminal
You are encouraged to solve this task according to the task description, using any language you may know.


Task

Demonstrate how to check whether the output device is a terminal or not.


Related task



6502 Assembly

Works with: Commodore 64
LDA $D011                ;screen control register 1
AND #%00100000           ;bit 5 clear = text mode, bit 5 set = gfx mode
BEQ isTerminal

Ada

Works with: GNAT

We use the interface to C library functions isatty() and fileno().

with Ada.Text_IO;          use Ada.Text_IO;
with Interfaces.C_Streams; use Interfaces.C_Streams;

procedure Test_tty is
begin
   if Isatty(Fileno(Stdout)) = 0 then
      Put_Line(Standard_Error, "stdout is not a tty.");
   else
      Put_Line(Standard_Error, "stdout is a tty.");
   end if;
end Test_tty;
Output:
$ ./test_tty 
stdout is a tty.
$ ./test_tty > /dev/null
stdout is not a tty.

C

Use isatty() on file descriptor to determine if it's a TTY. To get the file descriptor from a FILE* pointer, use fileno:

#include <unistd.h>   // for isatty()
#include <stdio.h>    // for fileno()

int main()
{
    puts(isatty(fileno(stdout))
          ? "stdout is tty"
          : "stdout is not tty");
    return 0;
}
Output:
$ ./a.out
stdout is tty

$ ./a.out > tmp
$ cat tmp
stdout is not tty

$ ./a.out | cat
stdout is not tty

C#

using System;

namespace CheckTerminal {
    class Program {
        static void Main(string[] args) {
            Console.WriteLine("Stdout is tty: {0}", Console.IsOutputRedirected);
        }
    }
}

C++

Translation of: C
#if _WIN32
#include <io.h>
#define ISATTY _isatty
#define FILENO _fileno
#else
#include <unistd.h>
#define ISATTY isatty
#define FILENO fileno
#endif

#include <iostream>

int main() {
    if (ISATTY(FILENO(stdout))) {
        std::cout << "stdout is a tty\n";
    } else {
        std::cout << "stdout is not a tty\n";
    }

    return 0;
}

COBOL

Works with GnuCOBOL.

      *>
      *> istty, check id fd 0 is a tty
      *> Tectonics: cobc -xj istty.cob
      *>            echo "test" | ./istty
      *>
       identification division.
       program-id. istty.

       data division.
       working-storage section.
       01 rc usage binary-long.

       procedure division.
       sample-main.

       call "isatty" using by value 0 returning rc
       display "fd 0 tty: " rc

       call "isatty" using by value 1 returning rc
       display "fd 1 tty: " rc upon syserr

       call "isatty" using by value 2 returning rc
       display "fd 2 tty: " rc

       goback.
       end program istty.

DISPLAY for fd 1 is directed to SYSERR to get some output during the various trials.

Output:
prompt$ cobc -xj istty.cob
fd 0 tty: +0000000001
fd 1 tty: +0000000001
fd 2 tty: +0000000001
prompt$ echo "test" | ./istty
fd 0 tty: +0000000000
fd 1 tty: +0000000001
fd 2 tty: +0000000001
prompt$ echo "test" | ./istty >/dev/null
fd 1 tty: +0000000000
prompt$ echo "test" | ./istty 2>/dev/tty
fd 0 tty: +0000000000
fd 1 tty: +0000000001
fd 2 tty: +0000000001
prompt$ echo "test" | ./istty 2>/dev/null
fd 0 tty: +0000000000
fd 2 tty: +0000000000

Common Lisp

Works with: SBCL
(with-open-stream (s *standard-output*)
  (format T "stdout is~:[ not~;~] a terminal~%" 
          (interactive-stream-p s)))
Output:
$ sbcl --script rc.lisp
stdout is a terminal
$ sbcl --script rc.lisp | cat
stdout is not a terminal
$ sbcl --script rc.lisp > foo.txt
$ cat foo.txt
stdout is not a terminal
Works with: ECL

We use the interface to C library functions isatty() and fileno(). It needs to be compiled to be executed.

(ffi:clines "
    #include <sys/ioctl.h>
    #include <unistd.h>
    int ttyPredicate() {
      return isatty(fileno(stdout)); 
     }")

(ffi:def-function
    ("ttyPredicate" c-ttyp)
    () :returning :int)

(defun tty-p()
  (if (= 1 (c-ttyp))
      t
      nil))

(format T "stdout is~:[ not~;~] a terminal~%" (tty-p))
(quit)

Compilation can be done with the following commands :

ecl --eval '(compile-file "file.lisp" :system-p t)' --eval '(quit)'

ecl --eval '(c:build-program "is-tty" :lisp-files (list "file.o"))' --eval '(quit)'

Output:
$ ./is-tty 
stdout is a terminal
$ ./is-tty  | cat -
stdout is not a terminal

Crystal

File.new("testfile").tty?   #=> false
File.new("/dev/tty").tty?   #=> true
STDOUT.tty?  #=> true

D

import std.stdio;

extern(C) int isatty(int);

void main() {
    writeln("Stdout is tty: ", stdout.fileno.isatty == 1);
}
Output:
prompt>a.out
Stdout is tty: true
prompt>a.out > out.txt
Stdout is tty: false

Factor

You have to know 1 is the correct file descriptor number:

IN: scratchpad USE: unix.ffi
IN: scratchpad 1 isatty

--- Data stack:
1

FreeBASIC

Open Cons For Output As #1
' Open Cons abre los flujos de entrada (stdin) o salida (stdout) estándar 
' de la consola para leer o escribir. 

If Err > 0 Then
    Print #1, "stdout is not a tty."
Else
    Print #1, "stdout is a tty."
End If  
Close #1
Sleep

Go

Tells a terminal apart from a pipe on Linux and Mac, which is probably exactly what you need.

package main

import (
    "os"
    "fmt"
)

func main() {
    if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
        fmt.Println("Hello terminal")
    } else {
        fmt.Println("Who are you? You're not a terminal")
    }
}
Output:
> hello
Hello terminal
> hello | cat
Who are you? You're not a terminal.

Haskell

module Main where

-- requires the unix package
-- https://hackage.haskell.org/package/unix
import System.Posix.Terminal (queryTerminal)
import System.Posix.IO (stdOutput)

main :: IO ()
main = do
  istty <- queryTerminal stdOutput
  putStrLn
    (if istty
       then "stdout is tty"
       else "stdout is not tty")
Output:
$ runhaskell istty.hs
stdout is tty
$ runhaskell istty.hs | cat
stdout is not tty

J

3=nc<'wd'

Explanation:

J does not have a concept of an "output device", so we approximate that by seeing whether we have bothered to define a the code which typically does graphical output.

The use of the phrase "output device" suggests that we are thinking about something like the unix `isatty` command. Here, stdout might be a file or might be a terminal. But in J we are often hosting our own user interaction environment. It's not uncommon for a J user to be on a web page where hitting enter sends a form request to a J interpreter which in turn composes an updated html presentation of current state which it sends to the browser. Or, the J user might be talking to a Java program which similarly wraps the J session (though this is older technology at this point). Or, the J user might be interacting with Qt. Or, sure, we might be talking to a tty and J might be sending its output straight to the tty. (But we can't know if that tty is hosted in emacs, running under control of a script on a remote machine via ssh, talking directly to a human user who happens to be in direct control of the session, or whatever else...)

The point being that in the general case the J programmer cannot know whether the concept of "terminal" has any relevance to the user.

But, like everyone else, we can certainly use heuristics.

But, correctness requires us to keep in mind that these will only be heuristics, and will sometimes be incorrect (hopefully not often enough to matter a lot...).

Javascript/NodeJS

node -p -e "Boolean(process.stdout.isTTY)"
true

Julia

if isa(STDOUT, Base.TTY)
    println("This program sees STDOUT as a TTY.")
else
    println("This program does not see STDOUT as a TTY.")
end
Output:
This program sees STDOUT as a TTY.

Kotlin

Works with: Ubuntu version 14.04
// Kotlin Native version 0.5

import platform.posix.*

fun main(args: Array<String>) {
    if (isatty(STDOUT_FILENO) != 0)
        println("stdout is a terminal")
    else
        println("stdout is not a terminal") 
}
Output:
stdout is a terminal

Lua

Works with: Lua version 5.1+

Using pure Lua, assuming a *NIX-like runtime environment ...

local function isTTY ( fd )
    fd = tonumber( fd ) or 1
    local ok, exit, signal = os.execute( string.format( "test -t %d", fd ) )
    return (ok and exit == "exit") and signal == 0 or false
end

print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )
Output:
$ lua istty.lua
stdin   true
stdout  true
stderr  true
$ cat /dev/null | lua istty.lua
stdin   false
stdout  true
stderr  true
$ lua istty.lua | tee
stdin   true
stdout  false
stderr  true
$ lua istty.lua 2>&1 | tee
stdin   true
stdout  false
stderr  false
Works with: Lua version 5.1+
Library: posix

You can accomplish the same results using the luaposix [1] library:

local unistd = require( "posix.unistd" )

local function isTTY ( fd )
    fd = tonumber( fd ) or 1
    local ok, err, errno = unistd.isatty( fd )
    return ok and true or false
end

print( "stdin", isTTY( 0 ) )
print( "stdout", isTTY( 1 ) )
print( "stderr", isTTY( 2 ) )

The output of this version is identical to the output of the first version.

Nemerle

There is no explicit way (ie isatty())to do this; however, if we assume that standard out is a terminal, we can check if the output stream has been redirected (presumably to something other than a terminal).

def isTerm = System.Console.IsOutputRedirected;

Nim

Using function "isatty" of standard module "terminal" which accepts a File as argument. As we want to redirect stdout, we write the messages on stderr.

import terminal

stderr.write if stdout.isatty: "stdout is a terminal\n" else: "stdout is not a terminal\n"
Output:
Command: ./check_output_dev
Result: stdout is a terminal
Command: ./check_output_dev >somefile
Result: stdout is not a terminal

OCaml

let () =
  print_endline (
    if Unix.isatty Unix.stdout
    then "Output goes to tty."
    else "Output doesn't go to tty."
  )

Testing in interpreted mode:

$ ocaml unix.cma istty.ml
Output goes to tty.

$ ocaml unix.cma istty.ml > tmp
$ cat tmp
Output doesn't go to tty.

$ ocaml unix.cma istty.ml | cat
Output doesn't go to tty.

Ol

(define (isatty? fd) (syscall 16 fd 19))
(print (if (isatty? stdout)
   "stdout is a tty."
   "stdout is not a tty."))

Perl

The -t function on a filehandle tells you whether it's a terminal.

$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'"
Terminal
$ perl -e "warn -t STDOUT ? 'Terminal' : 'Other'" > x.tmp
Other

Phix

without js -- (no input or output redirection in a browser!)
printf(1,"stdin:%t, stdout:%t, stderr:%t\n",{isatty(0),isatty(1),isatty(2)})
Output:
C:\Program Files (x86)\Phix>p test
stdin:true, stdout:true, stderr:true

C:\Program Files (x86)\Phix>p test > test.txt; type test.txt
stdin:true, stdout:false, stderr:true

C:\Program Files (x86)\Phix>p test 2> test.txt
stdin:true, stdout:true, stderr:false

C:\Program Files (x86)\Phix>type test.txt | p test
stdin:false, stdout:true, stderr:true

PHP

if(posix_isatty(STDOUT)) {
    echo "The output device is a terminal".PHP_EOL;
} else {
    echo "The output device is NOT a terminal".PHP_EOL;
}

Python

Pretty much the same as Check input device is a terminal#Python.

from sys import stdout
if stdout.isatty():
    print 'The output device is a teletype. Or something like a teletype.'
else:
    print 'The output device isn\'t like a teletype.'

Quackery

Translation of: Python
  [ $ |from sys import stdout
to_stack( 1 if stdout.isatty() else 0)|
    python ]                            is ttyout ( --> b )     

  ttyout if 
    [ say "Looks like a teletype." ] 
  else 
    [ say "Not a teletype." ]
Output:
Looks like a teletype.

Racket

(terminal-port? (current-output-port))

Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12

The .t method on a filehandle tells you whether it's going to the terminal. Here we use the note function to emit our result to standard error rather than standard out.

$ raku -e 'note $*OUT.t'
True
$ raku -e 'note $*OUT.t' >/dev/null
False

REXX


Programming note:   The comment about the REXX statements have to be on one line isn't quite true,
but because the REXX special variable SIGL is defined where it's executed, it makes coding simpler.


SIGL   is set to the REXX statement number where:

  •   a CALL statement is used
  •   a function is invoked
  •   a SIGNAL statement is used

Method used:   since REXX has no direct way of determining if the STDIN is a terminal or not, the REXX code (below)
actually   raises   (which is no way to run a railroad)   a syntax error when attempting to read the 2nd line from   STDIN,
which causes a routine   (named syntax:)   to get control,   determines where the syntax error occurred,   and returns
an appropriate string indicating if STDIN is a terminal   (or other).

Note that under VM/CMS, this can be accomplished with a (host) command within REXX and then examining the results.
On IBM mainframes, a user can have STDIN defined, but the terminal can be disconnected.

/*REXX program determines if the   STDIN   is a   terminal device   or  other.          */
signal on syntax                                 /*if syntax error, then jump ──► SYNTAX*/
say  'output device:'  testSTDIN()               /*displays   terminal   ──or──   other */
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
testSTDIN: syntax.=1;  signal .; .: z.= sigl;  call linein ,2; ..:  syntax.= 0; return z..
                                                 /* [↑]  must/should be all on one line.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
syntax:  z..= 'other'                            /*when a SYNTAX error occurs, come here*/
if syntax.  then do                              /*are we handling  STDIN  thingy error?*/
                 if sigl==z.  then z..= 'terminal';    signal ..     /*is this a stdin ?*/
                 end                             /* [↑]   can't use a   RETURN   here.  */

                                 /*    ···  handle other REXX syntax errors here  ···   */
output   when using the default input:
output device: terminal




The following is the output when used with R4 REXX:

output   when using the default input:
Reading console input (Press Ctrl-Z to quit):
                                   ◄■■■■■■■■ user input (pressed ENTER)  
                                   ◄■■■■■■■■ user input (pressed ENTER a 2nd time)                          
output device: 6

Ruby

f = File.open("test.txt")
p f.isatty          # => false
p STDOUT.isatty     # => true

Rust

/* Uses C library interface */

extern crate libc;

fn main() {
    let istty = unsafe { libc::isatty(libc::STDOUT_FILENO as i32) } != 0;
    if istty {
        println!("stdout is tty");
    } else {
        println!("stdout is not tty");
    }
}

Scala

Works with: Ubuntu version 14.04
import org.fusesource.jansi.internal.CLibrary._

object IsATty  extends App {

  var enabled = true

  def apply(enabled: Boolean): Boolean = {
    // We must be on some unix variant..
    try {
      enabled && isatty(STDOUT_FILENO) == 1
    }
    catch {
      case ignore: Throwable =>
        ignore.printStackTrace()
        false

    }
  }

    println("tty " + apply(true))
}

Standard ML

val stdoutRefersToTerminal : bool = Posix.ProcEnv.isatty Posix.FileSys.stdout

Swift

print(isatty(STDOUT_FILENO) != 0 ? "TTY" : "Not TTY" )

Tcl

To detect whether output is going to a terminal in Tcl, you check whether the stdout channel looks like a serial line (as those are indistinguishable from terminals). The simplest way of doing that is to see whether you can read the -mode or -xchar channel options, which are only present on serial channels:

set toTTY [dict exists [fconfigure stdout] -mode]
puts [expr {$toTTY ? "Output goes to tty" : "Output doesn't go to tty"}]

At the system call level, when Tcl is setting up the channels that correspond to the underlying stdout (and stdin and stderr) file descriptors, it checks whether the channels are network sockets (with getsockname()) or serial lines (with isatty()). This allows Tcl scripts to find out information about their calling environment (e.g., when they are run from inetd) with minimal code.

Demonstrating:

Assuming that the above script is stored in the file istty.tcl:

$ tclsh8.5 istty.tcl 
Output goes to tty
$ tclsh8.5 istty.tcl | cat
Output doesn't go to tty

Channel type discovery with older Tcl versions

Before Tcl 8.4, this discovery process is impossible; stdout always looks like it is going to a file. With 8.4, you can discover the channel type but you need slightly different (and less efficient, due to the thrown error in the non-tty case) code to do it.

set toTTY [expr {![catch {fconfigure stdout -mode}]}]

UNIX Shell

#!/bin/sh

if [ -t 1 ]
then
   echo "Output is a terminal"
else
   echo "Output is NOT a terminal" >/dev/tty
fi

Visual Basic .NET

Translation of: C#
Module Module1

    Sub Main()
        Console.WriteLine("Stdout is tty: {0}", Console.IsOutputRedirected)
    End Sub

End Module

Wren

Translation of: C

As there is currently no way to obtain this information via Wren CLI, we instead embed a Wren script in a C application and ask the host program to get it for us.

/* Check_output_device_is_a_terminal.wren */

class C {
    foreign static isOutputDeviceTerminal
}

System.print("Output device is a terminal = %(C.isOutputDeviceTerminal)")


We now embed this Wren script in the following C program, compile and run it.

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "wren.h"

void C_isOutputDeviceTerminal(WrenVM* vm) {
    bool isTerminal = (bool)isatty(fileno(stdout));
    wrenSetSlotBool(vm, 0, isTerminal);
}

WrenForeignMethodFn bindForeignMethod(
    WrenVM* vm,
    const char* module,
    const char* className,
    bool isStatic,
    const char* signature) {
    if (strcmp(module, "main") == 0) {
        if (strcmp(className, "C") == 0) {
            if (isStatic && strcmp(signature, "isOutputDeviceTerminal") == 0) {
                return C_isOutputDeviceTerminal;
            }
        }
    }
    return NULL;
}

static void writeFn(WrenVM* vm, const char* text) {
    printf("%s", text);
}

void errorFn(WrenVM* vm, WrenErrorType errorType, const char* module, const int line, const char* msg) {
    switch (errorType) {
        case WREN_ERROR_COMPILE:
            printf("[%s line %d] [Error] %s\n", module, line, msg);
            break;
        case WREN_ERROR_STACK_TRACE:
            printf("[%s line %d] in %s\n", module, line, msg);
            break;
        case WREN_ERROR_RUNTIME:
            printf("[Runtime Error] %s\n", msg);
            break;
    }
}

char *readFile(const char *fileName) {
    FILE *f = fopen(fileName, "r");
    fseek(f, 0, SEEK_END);
    long fsize = ftell(f);
    rewind(f);
    char *script = malloc(fsize + 1);
    fread(script, 1, fsize, f);
    fclose(f);
    script[fsize] = 0;
    return script;
}

int main() {
    WrenConfiguration config;
    wrenInitConfiguration(&config);
    config.writeFn = &writeFn;
    config.errorFn = &errorFn;
    config.bindForeignMethodFn = &bindForeignMethod;
    WrenVM* vm = wrenNewVM(&config);
    const char* module = "main";
    const char* fileName = "Check_output_device_is_a_terminal.wren";
    char *script = readFile(fileName);
    WrenInterpretResult result = wrenInterpret(vm, module, script);
    switch (result) {
        case WREN_RESULT_COMPILE_ERROR:
            printf("Compile Error!\n");
            break;
        case WREN_RESULT_RUNTIME_ERROR:
            printf("Runtime Error!\n");
            break;
        case WREN_RESULT_SUCCESS:
            break;
    }
    wrenFreeVM(vm);
    free(script);
    return 0;
}
Output:
$ ./Check_output_device_is_a_terminal
Output device is a terminal = true

$ ./Check_output_device_is_a_terminal > tmp
$ cat tmp
Output device is a terminal = false

$ ./Check_output_device_is_a_terminal | cat
Output device is a terminal = false

zkl

On Unix, check to see if stdout's st_mode is a character device.

const S_IFCHR=0x2000;
fcn S_ISCHR(f){ f.info()[4].bitAnd(S_IFCHR).toBool() }
S_ISCHR(File.stdout).println();
Output:
$ zkl bbb  # from the command line
True
$ zkl bbb | more
False
$ zkl bbb > foo.txt
$ cat foo.txt
False