Skip to content

Commit 00744c9

Browse files
committed
reworked the readme
1 parent d22ea37 commit 00744c9

File tree

1 file changed

+37
-247
lines changed

1 file changed

+37
-247
lines changed

README.md

Lines changed: 37 additions & 247 deletions
Original file line numberDiff line numberDiff line change
@@ -1,266 +1,56 @@
1-
# Terminal
1+
<p align="center">
2+
<img src="https://raw.githubusercontent.com//jupyter-xeus/cpp-terminal/readme/logo.svg" alt="CPP-Terminal logo"/>
3+
</p>
24

3-
`Terminal` is small header only library for writing terminal applications. It
4-
works on Linux, macOS and Windows (in the native `cmd.exe` console). It
5+
`CPP-Terminal` is a small and simple library for writing platform independent terminal applications. It works on Windows, MacOS and Linux and offers a simple programming interface. It
56
supports colors, keyboard input and has all the basic features to write any
67
terminal application.
78

8-
It has a small core ([terminal_base.h](cpp-terminal/terminal_base.h)) that has a
9-
few platform specific building blocks, and a platform independent library
10-
written on top using the ANSI escape sequences
11-
([terminal.h](cpp-terminal/terminal.h)).
9+
Until 2021, CPP-Terminal used to be a single header library. Now, CPP-Terminal consists out of multiple small and usage oriented headers:
10+
- `cpp-terminal/base.hpp`: everything for basic Terminal control
11+
- `cpp-terminal/input.hpp`: functions for gathering input
12+
- `cpp-terminal/prompt.hpp`: some variations of different prompts
13+
- `cpp-terminal/window.hpp`: a fully managed terminal window for terminal user interfaces (TUI)
14+
- `cpp-terminal/version.hpp`: macros with cpp-terminal's version number
1215

13-
This design has the advantage of having only a few lines to maintain on each
14-
platform, and the rest is platform independent. We intentionally limit
15-
ourselves to a subset of features that all work on all platforms natively. That
16-
way, any application written using `Terminal` will work everywhere out of the
17-
box, without emulation. At the same time, because the code of `Terminal` is
18-
short, one can easily debug it if something does not work, and have a full
19-
understanding how things work underneath.
16+
The library uses private header for platform dependent code:
17+
- `cpp-terminal/private/conversion.hpp`: Various conversions
18+
- `cpp-terminal/private/platform.hpp`: platform dependant code
2019

21-
## Examples
22-
23-
Several examples are provided to show how to use `Terminal`. Every example
24-
works natively on all platforms:
25-
26-
* [kilo.cpp](examples/kilo.cpp): the [kilo](https://github.com/snaptoken/kilo-src) text editor
27-
ported to C++ and `Terminal` instead of using Linux specific API.
28-
* [menu.cpp](examples/menu.cpp): Shows a menu on the screen
29-
* [keys.cpp](examples/keys.cpp): Listens for keys, showing their numbers
30-
* [colors.cpp](examples/colors.cpp): Shows how to print text in color to standard output
31-
32-
## How to use
33-
34-
The easiest is to just copy the two files `terminal.h` and `terminal_base.h`
35-
into your project. Consult the examples how to use it. You can just use the
36-
`terminal_base.h`, which is a standalone header file, if you only want the low
37-
level platform dependent functionality. Use `terminal.h`, which depends on
38-
`terminal_base.h`, if you also want the platform independent code to more
39-
easily print escape sequences and/or read and translate key codes.
40-
41-
## Documentation
42-
43-
We will start from the simplest concept (just printing a text on the screen)
44-
and then we will keep adding more features such as colors, cursor movement,
45-
keyboard input, etc., and we will be explaining how things work as we go.
46-
47-
### Printing
48-
49-
To print text into standard output, one can use `std::cout` in C++:
50-
```c++
51-
std::cout << "Some text" << std::endl;
52-
```
53-
One does not need `Terminal` for that.
54-
55-
### Colors
56-
57-
To print colors and other styles (such as bold), use the `Term::color()`
58-
function and `Term::fg` enum for foreground, `Term::bg` enum for background and
59-
`Term::style` enum for different styles (see the `colors.cpp` example):
60-
```c++
61-
#include <cpp-terminal/terminal.h>
62-
using Term::color;
63-
using Term::fg;
64-
using Term::bg;
65-
using Term::style;
66-
int main() {
67-
try {
68-
Term::Terminal term;
69-
std::string text = "Some text with "
70-
+ color(fg::red) + color(bg::green) + "red on green"
71-
+ color(bg::reset) + color(fg::reset) + " and some "
72-
+ color(style::bold) + "bold text" + color(style::reset) + ".";
73-
std::cout << text << std::endl;
74-
} catch(...) {
75-
throw;
76-
}
77-
return 0;
78-
}
79-
```
80-
One must call `Term::fg::reset`, `Term::bg::reset` and `Term::style::reset` to
81-
reset the given color or style.
82-
83-
One must create the `Term::Terminal` instance. In this case, the `Terminal`
84-
does nothing on Linux and macOS, but on Windows it checks if the program is
85-
running withing the Windows console and if so, enables ANSI escape codes in the
86-
console, which makes the console show colors properly. One must have a
87-
`try/catch` block in the main program to ensure the `Terminal`'s destructor
88-
gets called (even if an unhandled exception occurs), which will put the console
89-
into the original mode.
90-
91-
The program might decide to print colors not only if it is in a terminal (which
92-
can be checked by `term.is_stdout_a_tty()`), but also when not run in a
93-
terminal, some examples:
94-
95-
* Running on a CI, e.g. AppVeyor, Travis-CI and Azure Pipelines all show colors
96-
properly
97-
* Using `less -r` shows colors properly (but `less` does not)
98-
* Printing colors in program output in a Jupyter notebook (and then possibly
99-
converting such colors from ANSI sequences to html)
100-
101-
An example when the program might not print colors is when the standard output
102-
gets redirected to a file (say, compiler error messages using `g++ a.cpp >
103-
log`), and then the file is read directly in some editor.
104-
105-
The `color()` function always returns a string with the proper ANSI sequence.
106-
The program might wrap this in a macro, that will check some program variable
107-
if it should print colors and only call `color()` if colors should be printed.
108-
109-
### Cursor movement and its visibility
110-
111-
The next step up is to allow cursor movement and other ANSI sequences. For
112-
example, here is how to render a simple menu (see `menu.cpp` example) and print
113-
it on the screen:
114-
```c++
115-
void render(int rows, int cols, int pos)
116-
{
117-
std::string scr;
118-
scr.reserve(16*1024);
119-
120-
scr.append(cursor_off());
121-
scr.append(move_cursor(1, 1));
122-
123-
for (int i=1; i <= rows; i++) {
124-
if (i == pos) {
125-
scr.append(color(fg::red));
126-
scr.append(color(bg::gray));
127-
scr.append(color(style::bold));
128-
} else {
129-
scr.append(color(fg::blue));
130-
scr.append(color(bg::green));
131-
}
132-
scr.append(std::to_string(i) + ": item");
133-
scr.append(color(bg::reset));
134-
scr.append(color(fg::reset));
135-
scr.append(color(style::reset));
136-
if (i < rows) scr.append("\n");
137-
}
138-
139-
scr.append(move_cursor(rows / 2, cols / 2));
140-
141-
scr.append(cursor_on());
142-
143-
std::cout << scr << std::flush;
144-
}
145-
```
146-
This will accumulate the following operations into a string:
20+
CPP-Terminal tries to be a small and simple replacement for ncurses. This approach keeps the code small and maintainable, but also easy to extend it's functionality. We limit ourselves to a subset of features that work on all supported platforms without needing to worry about style differences or other changes. Any application written with `CPP-Terminal` will work everywhere out of the box natively, without emulation or extra work. The small codebase makes CPP-Terminal easy to debug and extend, as well as understanding what happens behind the scenes in the library's core.
14721

148-
* Turn off the cursor (so that the terminal does not show the cursor
149-
quickly moving around the screen)
150-
* Move the cursor to the `(1,1)` position
151-
* Print the menu in color and highlighting the selected item (specified by
152-
`pos`)
153-
* Move the cursor to the middle of the screen
154-
* Turn on the cursor
15522

156-
and print the string. The `std::flush` ensures that the whole string ends up on
157-
the screen.
158-
159-
### Saving the original screen and restoring it
160-
161-
It is a good habit to restore the original terminal screen (and cursor
162-
position) if we are going move the cursor around and draw (as in the previous
163-
section). To do that, call the `save_screen()` method:
164-
```c++
165-
Term::Terminal term;
166-
term.save_screen();
167-
```
168-
This issues the proper ANSI sequences to the terminal to save the screen. The
169-
`Terminal`'s destructor will then automatically issue the corresponding
170-
sequences to restore the original screen and the cursor position.
171-
172-
### Keyboard input
173-
174-
The final step is to enable keyboard input. To do that, one must set the
175-
terminal in a so called "raw" mode:
176-
```c++
177-
Terminal term(true);
178-
```
179-
On Linux and macOS, this disables terminal input buffering, thus every key
180-
press is immediately sent to the application (otherwise one has to press ENTER
181-
before any input is sent). On Windows, this turns on ANSI keyboard sequences
182-
for key presses.
183-
184-
The `Terminal`'s destructor then properly restores the terminal to the original
185-
mode on all platforms.
186-
187-
One can then wait and read individual keys and do something based on
188-
that, such as (see `menu.cpp`):
189-
```c++
190-
int key = term.read_key();
191-
switch (key) {
192-
case Key::ARROW_UP: if (pos > 1) pos--; break;
193-
case Key::ARROW_DOWN: if (pos < rows) pos++; break;
194-
case 'q':
195-
case Key::ESC:
196-
on = false; break;
197-
}
198-
```
199-
200-
Now we have all the features that are needed to write any terminal application.
201-
See `kilo.cpp` for an example of a simple full screen editor.
202-
203-
## Similar Projects
204-
205-
### Colors
206-
207-
Libraries to handle color output.
208-
209-
C++:
210-
211-
* [rang](https://github.com/agauniyal/rang)
212-
213-
### Drawing
214-
215-
JavaScript:
216-
217-
* [node-drawille](https://github.com/madbence/node-drawille)
218-
219-
### Prompt
220-
221-
Libraries to handle a prompt in terminals.
222-
223-
C and C++:
224-
225-
* [readline](https://tiswww.case.edu/php/chet/readline/rltop.html)
226-
* [libedit](http://thrysoee.dk/editline/)
227-
* [linenoise](https://github.com/antirez/linenoise)
228-
* [replxx](https://github.com/AmokHuginnsson/replxx)
229-
230-
Python:
231-
232-
* [python-prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit)
23+
## Examples
24+
We have created serval examples to show possible use cases of CPP-Terminal and to get you started more quickly. Every example works natively on all platforms in the exact same way:
25+
- [base.cpp](examples/base.cpp): basic color, style and unicode demo
26+
- [kilo.cpp](examples/kilo.cpp): the [kilo](https://github.com/snaptoken/kilo-src) text editor
27+
ported to C++ and `CPP-Terminal` instead of using Linux specific API
28+
- [menu.cpp](examples/menu.cpp): An interactive menu using only the contents of `cpp-terminal/base.hpp`
29+
- [menu_window.cpp](examples/menu_window.cpp): An interactive menu using the fully managed windowing system from `cpp-terminal/window.hpp`
30+
- [keys.cpp](examples/keys.cpp): Interactively shows the keys pressed
23331

234-
### General TUI libraries
32+
## Supported platforms
23533

236-
C and C++:
34+
| Platform | Supported versions | Coverage by unit test |
35+
| -------- | ------------------ | --------------------- |
36+
| Windows | 10 and higher* | MSVC |
37+
| MacOS | All supported | Apple-clang |
38+
| Linux | All supported | GCC |
23739

238-
* [curses](https://en.wikipedia.org/wiki/Curses_%28programming_library%29) and [ncurses](https://www.gnu.org/software/ncurses/ncurses.html)
239-
* [Newt](https://en.wikipedia.org/wiki/Newt_(programming_library))
240-
* [termbox](https://github.com/nsf/termbox)
241-
* [FTXUI](https://github.com/ArthurSonzogni/FTXUI)
242-
* [ImTui](https://github.com/ggerganov/imtui)
40+
* Windows versions prior 10 have no proper terminal supports. They are lacking ANSI support which is required by CPP-Terminal.
24341

244-
Python:
42+
## How to use
24543

246-
* [urwid](http://urwid.org/)
247-
* [python-prompt-toolkit](https://github.com/prompt-toolkit/python-prompt-toolkit)
248-
* [npyscreen](http://www.npcole.com/npyscreen/)
249-
* [curtsies](https://github.com/bpython/curtsies)
44+
Adding CPP-Terminal to your project is really easy. We have collected various ways with easy how-to's [in our documentation](https://github.com/jupyter-xeus/cpp-terminal/wiki/Adding-CPP-Terminal-to-your-ptoject).
25045

251-
Go:
46+
## Documentation
25247

253-
* [gocui](https://github.com/jroimartin/gocui)
254-
* [clui](https://github.com/VladimirMarkelov/clui)
255-
* [tview](https://github.com/rivo/tview)
256-
* [termbox-go](https://github.com/nsf/termbox-go)
257-
* [termui](https://github.com/gizak/termui)
258-
* [tcell](https://github.com/gdamore/tcell)
48+
CPP-Terminal's documentation can be found [here](https://github.com/jupyter-xeus/cpp-terminal/wiki).
25949

260-
Rust:
50+
## Contributing
26151

262-
* [tui-rs](https://github.com/fdehau/tui-rs)
52+
Contributing to CPP-Terminal is highly appreciated and can be done in more ways than code. Extending it's functionality, reporting or fixing bugs and extending the documentations are just a few of them.
26353

264-
JavaScript:
54+
## License
26555

266-
* [blessed](https://github.com/chjj/blessed) and [blessed-contrib](https://github.com/yaronn/blessed-contrib)
56+
CPP-Terminal is licensed under the terms of [the MIT License](https://github.com/jupyter-xeus/cpp-terminal/blob/master/LICENSE) by Ondřej Čertík.

0 commit comments

Comments
 (0)