Skip to content

Commit ae74dab

Browse files
committed
Readme
1 parent ca116fc commit ae74dab

File tree

1 file changed

+284
-0
lines changed

1 file changed

+284
-0
lines changed

README.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
# Solo Screen
2+
3+
Screen is a terminal emulator written in pure PHP. It powers [Solo for Laravel](https://github.com/soloterm/solo) and
4+
can be used to build rich text-based user interfaces in any PHP application.
5+
6+
> [!NOTE]
7+
> Screen is a library intended to be integrated into PHP applications. It is not a standalone terminal application.
8+
9+
## About Terminal Emulators
10+
11+
A terminal emulator is software that replicates the functionality of a classic hardware computer terminal. It processes
12+
text input and output along with special control sequences (ANSI escape codes) that control formatting, cursor movement,
13+
and other terminal features.
14+
15+
Terminal emulators interpret these escape sequences to:
16+
17+
- Position the cursor
18+
- Set text colors and styles (bold, underline, etc.)
19+
- Clear parts of the screen
20+
- Handle special character sets
21+
- And much more
22+
23+
Screen implements this functionality in pure PHP, allowing developers to build terminal user interfaces without relying
24+
on external dependencies or native code.
25+
26+
## Why this exists
27+
28+
Screen was originally created to solve a specific problem in [Solo for Laravel](https://github.com/soloterm/solo).
29+
30+
Solo provides a TUI (Text User Interface) that runs multiple processes simultaneously in separate panels, similar to
31+
tmux. However, when these processes output ANSI escape codes for cursor movement and screen manipulation, they could
32+
potentially "break out" of their visual containers and interfere with other parts of the interface.
33+
34+
To solve this problem, Screen creates a virtual terminal buffer where:
35+
36+
1. All ANSI operations (cursor movements, color changes, screen clears) happen safely within an isolated environment
37+
2. The final rendered state is captured after all operations are processed
38+
3. Only the final visual output is displayed to the user's terminal
39+
40+
This approach provides complete control over how terminal output is rendered, ensuring that complex ANSI operations stay
41+
contained within their designated areas. While initially built for Solo, Screen has evolved into a standalone library
42+
that can be used in any PHP application requiring terminal emulation.
43+
44+
## Features
45+
46+
- **Pure PHP Implementation**: Only one dependency ([Grapheme](https://github.com/soloterm/grapheme), another Solo
47+
library)
48+
- **Comprehensive ANSI Support**: Handles cursor positioning, text styling, and screen manipulation
49+
- **Unicode/Multibyte Support**: Properly handles UTF-8 characters including emojis and wide characters
50+
- **Buffer Management**: Maintains separate buffers for text content and styling
51+
- **Character Width Handling**: Correctly calculates display width for CJK and other double-width characters
52+
- **Scrolling**: Support for vertical scrolling with proper content management
53+
54+
## Installation
55+
56+
Install via Composer:
57+
58+
```shell
59+
composer require soloterm/screen
60+
```
61+
62+
## Requirements
63+
64+
- PHP 8.1 or higher
65+
- mbstring extension
66+
67+
## Basic Usage
68+
69+
Here's a simple example of using Screen:
70+
71+
```php
72+
use SoloTerm\Screen\Screen;
73+
74+
// Create a screen with dimensions (columns, rows)
75+
$screen = new Screen(80, 24);
76+
77+
// Write text and ANSI escape sequences
78+
$screen->write("Hello, \e[1;32mWorld!\e[0m");
79+
80+
// Move cursor and add more text
81+
$screen->write("\e[5;10HPositioned text");
82+
83+
// Get the rendered content
84+
echo $screen->output();
85+
```
86+
87+
## Core Concepts
88+
89+
Screen operates with several key components:
90+
91+
### Screen
92+
93+
The main class that coordinates all functionality. It takes care of cursor positioning, content writing, and rendering
94+
the final output.
95+
96+
```php
97+
$screen = new Screen(80, 24); // width, height
98+
$screen->write("Text and ANSI codes");
99+
```
100+
101+
### Buffers
102+
103+
Screen uses multiple buffer types to track content and styling:
104+
105+
- **PrintableBuffer**: Stores visible characters and handles width calculations
106+
- **AnsiBuffer**: Tracks styling information (colors, bold, underline, etc.)
107+
108+
### ANSI Processing
109+
110+
Screen correctly handles ANSI escape sequences for:
111+
112+
- Cursor movement (up, down, left, right, absolute positioning)
113+
- Text styling (colors, bold, italic, underline)
114+
- Screen clearing and line manipulation
115+
- Scrolling
116+
117+
## Advanced Features
118+
119+
### Cursor Positioning
120+
121+
```php
122+
// Move cursor to position (row 5, column 10)
123+
$screen->write("\e[5;10H");
124+
125+
// Move cursor up 3 lines
126+
$screen->write("\e[3A");
127+
128+
// Save and restore cursor position
129+
$screen->write("\e7"); // Save
130+
$screen->write("More text");
131+
$screen->write("\e8"); // Restore
132+
```
133+
134+
### Text Styling
135+
136+
```php
137+
// Bold red text
138+
$screen->write("\e[1;31mImportant message\e[0m");
139+
140+
// Background colors
141+
$screen->write("\e[44mBlue background\e[0m");
142+
143+
// 256-color support
144+
$screen->write("\e[38;5;208mOrange text\e[0m");
145+
146+
// RGB colors
147+
$screen->write("\e[38;2;255;100;0mCustom color\e[0m");
148+
```
149+
150+
### Screen Manipulation
151+
152+
```php
153+
// Clear screen
154+
$screen->write("\e[2J");
155+
156+
// Clear from cursor to end of line
157+
$screen->write("\e[0K");
158+
159+
// Insert lines
160+
$screen->write("\e[2L");
161+
162+
// Scroll up
163+
$screen->write("\e[2S");
164+
```
165+
166+
## Custom Integrations
167+
168+
You can respond to terminal queries by setting a callback:
169+
170+
```php
171+
$screen->respondToQueriesVia(function($response) {
172+
// Process response (like cursor position)
173+
echo $response;
174+
});
175+
```
176+
177+
> [!NOTE]
178+
> This is still a work in progress. We need some more tests / use cases here.
179+
180+
## Example: Building a Simple UI
181+
182+
```php
183+
use SoloTerm\Screen\Screen;
184+
185+
$screen = new Screen(80, 24);
186+
187+
// Draw a border
188+
$screen->write("┌" . str_repeat("─", 78) . "┐\n");
189+
for ($i = 0; $i < 22; $i++) {
190+
$screen->write("│" . str_repeat(" ", 78) . "│\n");
191+
}
192+
$screen->write("└" . str_repeat("─", 78) . "┘");
193+
194+
// Add a title
195+
$screen->write("\e[1;30H\e[1;36mMy Application\e[0m");
196+
197+
// Add some content
198+
$screen->write("\e[5;5HWelcome to the application!");
199+
$screen->write("\e[7;5HPress 'q' to quit.");
200+
201+
// Render
202+
echo $screen->output();
203+
```
204+
205+
## Handling Unicode and Wide Characters
206+
207+
Screen properly handles Unicode characters including emoji and CJK characters that take up multiple columns:
208+
209+
```php
210+
$screen->write("Regular text: Hello");
211+
$screen->write("\nWide characters: 你好世界");
212+
$screen->write("\nEmoji: 🚀 👨‍👩‍👧‍👦 🌍");
213+
```
214+
215+
## Testing
216+
217+
Screen includes a comprehensive testing suite that features a unique visual comparison system:
218+
219+
```shell
220+
composer test
221+
```
222+
223+
### Visual Testing
224+
225+
Screen employs an innovative screenshot-based testing approach (see `ComparesVisually` trait) that validates the visual
226+
output:
227+
228+
1. The test renders content in a real terminal (iTerm)
229+
2. It captures a screenshot of the terminal output
230+
3. It runs the same content through the Screen emulator
231+
4. It captures a screenshot of the emulated output
232+
5. It compares the screenshots pixel-by-pixel to ensure accuracy
233+
234+
This testing strategy ensures that Screen's emulation accurately matches real terminal behavior, especially for complex
235+
scenarios involving:
236+
237+
- Multi-byte characters
238+
- Complex ANSI formatting
239+
- Cursor movements
240+
- Scrolling behavior
241+
- Line wrapping
242+
243+
For environments without screenshot capabilities, tests can fall back to fixture-based comparison, making the test suite
244+
versatile for CI/CD pipelines.
245+
246+
To enable screenshots for all tests, use the following command:
247+
248+
```shell
249+
ENABLE_SCREENSHOT_TESTING=1 composer test
250+
```
251+
252+
To enable screenshots for only the tests that dont' already have fixtures, use the following command:
253+
254+
```shell
255+
ENABLE_SCREENSHOT_TESTING=2 composer test
256+
```
257+
258+
## Contributing
259+
260+
Contributions are welcome! Please feel free to submit a pull request.
261+
262+
## License
263+
264+
The MIT License (MIT).
265+
266+
## Support
267+
268+
This is free! If you want to support me:
269+
270+
- Sponsor my open source work: [aaronfrancis.com/backstage](https://aaronfrancis.com/backstage)
271+
- Check out my courses:
272+
- [Mastering Postgres](https://masteringpostgres.com)
273+
- [High Performance SQLite](https://highperformancesqlite.com)
274+
- [Screencasting](https://screencasting.com)
275+
- Help spread the word about things I make
276+
277+
## Credits
278+
279+
Solo Screen was developed by Aaron Francis. If you like it, please let me know!
280+
281+
- Twitter: https://twitter.com/aarondfrancis
282+
- Website: https://aaronfrancis.com
283+
- YouTube: https://youtube.com/@aarondfrancis
284+
- GitHub: https://github.com/aarondfrancis/solo

0 commit comments

Comments
 (0)