term_ctrl/
lib.rs

1// Copyright 2017 Lyndon Brown
2//
3// Licensed under the MIT license or the Apache license (version 2.0), at your option. You may not
4// copy, modify, or distribute this file except in compliance with said license. You can find copies
5// of these licenses either in the LICENSE-MIT and LICENSE-APACHE files, or alternatively at
6// <http://opensource.org/licenses/MIT> and <http://www.apache.org/licenses/LICENSE-2.0>
7// respectively.
8
9//! ANSI terminal text formatting assistant
10//!
11//! Some virtual-terminals (ANSI ones being the focus here) have a feature of allowing command-line
12//! programs executed in them to request that certain limited formatting effects such as colour or
13//! boldness be applied to portions of the text the program outputs for them to display. This is
14//! achieved through the program embedding special “ANSI control” byte sequences into that text
15//! output. This can prove very useful for instance in highlighting error notices.
16//!
17//! The purpose of this crate is to offer functionality to assist in generating and using such
18//! control sequences.
19//!
20//! Note that such formatting should only be used when the `stdout` stream (or `stderr` as
21//! applicable) is connected to an actual terminal that will process and use them (you wouldn't want
22//! these control sequences to exist in output that the user is having the terminal redirect into a
23//! text file or another program as then it would just be treated as a part of the text and lead to
24//! garbled output and confusion). Some utility functions are provided within the [support mod] to
25//! assist you with determining appropriateness of using formatted output.
26//!
27//! # Predefined sequences
28//!
29//! There is no strict need to actually understand how to construct such control sequences to make
30//! use of the formatting they offer; many predefined sequences are available for your use in the
31//! [predefined mod].
32//!
33//! To make use of these simply inject them into the right points of a to-be-printed string via
34//! format arguments, as demonstrated below. Remember not to forget to make use of a reset after the
35//! text to be formatted. For instance:
36//!
37//! ```rust
38//! use term_ctrl::predefined::{RESET, colours::fg::RED};
39//! println!("{}Error:{} You made an error!", RED, RESET);
40//! ```
41//!
42//! In the example just given, the text “<span style="color:#c00">Error:</span>” will be highlighted
43//! in red. Of course as mentioned earlier, you should only use the colour sequences if output is
44//! actually connected to a terminal (and that the terminal has not redirected it, so do not assume
45//! output to stdout is okay). Here the example is modified to use a helper to check suitability and
46//! a filter to control use:
47//!
48//! ```rust
49//! use term_ctrl::predefined::{RESET, colours::fg::RED};
50//! let format = term_ctrl::support::fmt_supported_stdout();
51//! let filter = |seq| { match format { true => seq, false => "" } };
52//! println!("{}Error:{} You made an error!", filter(RED), filter(RESET));
53//! ```
54//!
55//! Note, when resetting to normal, be sure to always use the proper reset sequence. Do not make the
56//! mistake of setting text colour to black and presuming that this achieves the same thing; it does
57//! not. (Consider that some people have black text on a white background in their terminal, whilst
58//! others use the opposite! Black text on a black background does not work very well!).
59//!
60//! # Constructing sequences
61//!
62//! Although understanding the sequences is not required, there are however benefits to be gained
63//! from it, since for instance not every possible combination can reasonably be provided in
64//! predefined form, and you may be able to achieve greater efficiency by constructing a custom one
65//! rather than using multiple predefines in sequence.
66//!
67//! Let’s take a quick look at the sequence itself, then we can move on to discuss a macro which
68//! helps make custom construction very easy.
69//!
70//! ## The sequence pattern
71//!
72//! The sequence pattern consists of four component parts:
73//!
74//! <table style="width:auto">
75//!     <tr><td>1</td><td>ESC ('\u{1B}')</td><td>The escape (␛) char, Unicode 0x1B</td></tr>
76//!     <tr><td>2</td><td>'['</td><td>An opening bracket char</td></tr>
77//!     <tr><td>3</td><td colspan="2">One or more numbers using a semi-colon (';') as a separator</td></tr>
78//!     <tr><td>4</td><td>'m'</td><td>A lower-case letter m</td></tr>
79//! </table>
80//!
81//! In other words a pattern of: `"\u{1B}[` <em><codes\></em> `m"`
82//!
83//! Every control sequence fits this template, and it is the set of numbers included in it which
84//! determine the precise formatting nature of the request. As a quick example, the sequence of
85//! `"\u{1B}[31;1m"` specifies two numbers, `31` which corresponds to red text, and `1` which
86//! corresponds to bold text (the set of available number codes are discussed shortly).
87//!
88//! Typically each of the individual numbers given corresponds to a particular effect, however as we
89//! will see shortly there are a couple of exceptions where multiple numbers are used.
90//!
91//! Before we continue, understand that the effects specified are applied in sequence and remain in
92//! effect until changed or reset by a subsequent code in the sequence or by such a code in a later
93//! sequence. Hence in the example given earlier, a sequence is used to enable red text, this is
94//! followed by some text to which this formatting applies, then a new sequence is given that issues
95//! the reset-all code. There are codes available for removing specific effects or resetting just
96//! foreground or background-highlight colours. There is also the catch-all code `0` for resetting
97//! everything to normal.
98//!
99//! ## Macro construction
100//!
101//! As just mentioned, a macro (called [`seq`]) is provided to assist with constructing sequences.
102//! All you have to do is provide it with a list of decimal numbers and it will construct a string
103//! of the above pattern that contains them. An example:
104//!
105//! ```rust
106//! use term_ctrl::seq;
107//! assert_eq!("\u{1B}[1;2;3m", seq!(1, 2, 3));
108//! ```
109//!
110//! Note that you are not restricted to pure numeric literals, string literals work also:
111//!
112//! ```rust
113//! use term_ctrl::seq;
114//! assert_eq!("\u{1B}[1;2;3m", seq!("1", "2", "3"));
115//! assert_eq!("\u{1B}[1;2;3m", seq!("1;2", 3));
116//! ```
117//!
118//! Convenience macros are also provided for constructing 256-colour and RGB colour code sets for
119//! use in a sequence (they do not generate the full sequence, just a multi-code set of numbers to
120//! use in a sequence).
121//!
122//! ## Number code chart
123//!
124//! The following is a guide to the available number codes and what they correspond to. In most
125//! cases a single number code corresponds to a single effect, however there are also those that
126//! require a sequence of multiple numbers (with the normal semi-colon separator).
127//!
128//! ### Effects
129//!
130//! <table>
131//!     <thead>
132//!         <tr><th>Code</th><th>Effect</th><th>Code</th><th>Effect</th></tr>
133//!     </thead>
134//!     <tbody>
135//!         <tr><td>0</td><td>Normal (reset)</td><td>20</td><td><a href="https://en.wikipedia.org/wiki/Fraktur_(script)">Fraktur</a> on</td></tr>
136//!         <tr><td>1</td><td>Bold on (increase intensity)</td><td>21</td><td>Double-underline on</td></tr>
137//!         <tr><td>2</td><td>Dim on (faint, or decrease intensity)</td><td>22</td><td>Bold and dim off</td></tr>
138//!         <tr><td>3</td><td>Italic on</td><td>23</td><td>Italic and Fraktur off</td></tr>
139//!         <tr><td>4</td><td>Underline on</td><td>24</td><td>Underline (and double-underline) off</td></tr>
140//!         <tr><td>5</td><td>Blink on</td><td>25</td><td>Blink off (aka “steady”)</td></tr>
141//!         <tr><td>6</td><td>Rapid-blink on</td><td>26</td><td><em>unused?</em></td></tr>
142//!         <tr><td>7</td><td>“Inverse” on (swap fg/bg colours)</td><td>27</td><td>Inverse off (aka “positive”)</td></tr>
143//!         <tr><td>8</td><td>Invisible (hidden) on</td><td>28</td><td>Invisible off (aka “visible”)</td></tr>
144//!         <tr><td>9</td><td>Strike-through on</td><td>29</td><td>Strike-through off</td></tr>
145//!     </tbody>
146//! </table>
147//!
148//! Code zero (`0`) resets all effects and colour selections to defaults.
149//!
150//! Note that codes `22`-`25` and `27`-`29` provide for removing specific effects.
151//!
152//! Codes `10-19` (unlisted above) are used for font selection. Code `10` selects the primary
153//! (default) font. Codes `11`-`19` select alternate fonts 1-9.
154//!
155//! ### Basic colours
156//!
157//! The basic colour palettes consist of a simple set of eight colours for each of foreground and
158//! background-highlight uses. There are also “bright” variants.
159//!
160//! <table>
161//!     <thead>
162//!         <tr><th>Colour</th><th>Foreground</th><th>Background</th><th>Bright foreground</th><th>Bright background</th></tr>
163//!     </thead>
164//!     <tbody>
165//!         <tr><td>Black</td><td>30</td><td>40</td><td>90</td><td>100</td></tr>
166//!         <tr><td>Red</td><td>31</td><td>41</td><td>91</td><td>101</td></tr>
167//!         <tr><td>Green</td><td>32</td><td>42</td><td>92</td><td>102</td></tr>
168//!         <tr><td>Yellow</td><td>33</td><td>43</td><td>93</td><td>103</td></tr>
169//!         <tr><td>Blue</td><td>34</td><td>44</td><td>94</td><td>104</td></tr>
170//!         <tr><td>Magenta</td><td>35</td><td>45</td><td>95</td><td>105</td></tr>
171//!         <tr><td>Cyan</td><td>36</td><td>46</td><td>96</td><td>106</td></tr>
172//!         <tr><td>White</td><td>37</td><td>47</td><td>97</td><td>107</td></tr>
173//!         <tr><td><em>Extended</em></td><td>38</td><td>48</td><td><em>n/a</em></td><td><em>n/a</em></td></tr>
174//!         <tr><td><em>Default</em> (reset)</td><td>39</td><td>49</td><td><em>n/a</em></td><td><em>n/a</em></td></tr>
175//!     </tbody>
176//! </table>
177//!
178//! The “extended” codes `38` and `48` are used to start multi-code “extended” colour palette
179//! selections, as discussed shortly.
180//!
181//! The “default” codes `39` and `49` are used to reset foreground and background-highlight colours
182//! respectively to defaults, and apply to bright and extended colouring also.
183//!
184//! Note that the “bright” codes are not actually a part of the official ANSI standard, apparently.
185//!
186//! ### Extended range colours
187//!
188//! Wider choice of colours than above is made available as *extended* colours through use of a
189//! sequence of codes (using the normal semi-colon separator).
190//!
191//! There are two ranges available, an 8-bit (256 colour) range, and a 24-bit RGB range. Both begin
192//! with either `38` to choose text (foreground colouring) or `48` for background-highlight
193//! colouring. This is followed by `5` for specifying 256-colour or `2` for specifying RGB colour.
194//! With 256-colour a final third number with a value in the range of 0-255 selects the specific
195//! colour. With RGB, three numbers must be given, each corresponding to red, green and blue
196//! respectively, and each also being of a value in the range 0-255.
197//!
198//! [See here][Xterm_256color_chart.svg] for a 256-colour chart.
199//!
200//! As an example, `seq!(38,5,238)` changes the colour of text (not background) since it starts with
201//! `38`, it is providing a 256-colour palette selection (the `5`), and is specifically selecting
202//! colour `238` from that palette.
203//!
204//! As another example, `seq!(48,2,180,15,70)` changes the colour of the text background since it
205//! starts with `48`, it is providing an RGB colour (the `2`), and is then followed with RGB values
206//! of `180` for red, `15` for green and `70` for blue.
207//!
208//! # Resources
209//!
210//! A collection of useful or informative related resources:
211//!
212//!  - [Wikipedia: ANSI_escape_code][wikipedia_ANSI_escape_code_SGR] (Specifically the CSI-SGR stuff)
213//!  - [Wikipedia: Xterm][wikipedia_Xterm]
214//!  - [Xterm control sequence documentation][xterm_ctlseqs]
215//!  - [256-color chart][Xterm_256color_chart.svg]
216//!
217//! [support mod]: mod@crate::support
218//! [predefined mod]: mod@crate::predefined
219//! [`seq`]: macro@seq
220//! [Xterm_256color_chart.svg]: https://upload.wikimedia.org/wikipedia/commons/1/15/Xterm_256color_chart.svg
221//! [wikipedia_ANSI_escape_code_SGR]: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR
222//! [wikipedia_Xterm]: https://en.wikipedia.org/wiki/Xterm
223//! [xterm_ctlseqs]: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html
224
225#![no_std]
226
227extern crate atty;
228#[cfg(windows)]
229extern crate winapi;
230
231pub mod codes;
232mod macros;
233pub mod predefined;
234pub mod support;