Skip to content

Commit 6e43289

Browse files
committed
add terminal tool class
1 parent 466f114 commit 6e43289

File tree

2 files changed

+245
-0
lines changed

2 files changed

+245
-0
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
11
# cli-utils
22

33
some utils for the CLI
4+
5+
## Install
6+
7+
```bash
8+
composer require toolkit/cli-utils
9+
```
10+
11+
## cli color
12+
13+
![colors](./example/all-color-style.jpg)
14+
15+
## license
16+
17+
MIT

src/Terminal.php

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: inhere
5+
* Date: 2017-03-08
6+
* Time: 9:35
7+
*/
8+
9+
namespace Toolkit\Cli;
10+
11+
/**
12+
* Class Terminal - terminal control by ansiCode
13+
* @package Toolkit\Cli
14+
*
15+
* 2K 清除本行
16+
* \x0D = \r = 13 回车,回到行首
17+
* ESC = \x1B = \033 = 27
18+
*/
19+
final class Terminal
20+
{
21+
const BEGIN_CHAR = "\033[";
22+
const END_CHAR = "\033[0m";
23+
24+
// Control cursor code name list. more @see [[self::$ctrlCursorCodes]]
25+
const CUR_HIDE = 'hide';
26+
const CUR_SHOW = 'show';
27+
const CUR_SAVE_POSITION = 'savePosition';
28+
const CUR_RESTORE_POSITION = 'restorePosition';
29+
const CUR_UP = 'up';
30+
const CUR_DOWN = 'down';
31+
const CUR_FORWARD = 'forward';
32+
const CUR_BACKWARD = 'backward';
33+
const CUR_NEXT_LINE = 'nextLine';
34+
const CUR_PREV_LINE = 'prevLine';
35+
const CUR_COORDINATE = 'coordinate';
36+
37+
// Control screen code name list. more @see [[self::$ctrlScreenCodes]]
38+
const CLEAR = 'clear';
39+
const CLEAR_BEFORE_CURSOR = 'clearBeforeCursor';
40+
const CLEAR_LINE = 'clearLine';
41+
const CLEAR_LINE_BEFORE_CURSOR = 'clearLineBeforeCursor';
42+
const CLEAR_LINE_AFTER_CURSOR = 'clearLineAfterCursor';
43+
44+
const SCROLL_UP = 'scrollUp';
45+
const SCROLL_DOWN = 'scrollDown';
46+
47+
/**
48+
* current class's instance
49+
* @var self
50+
*/
51+
private static $instance;
52+
53+
/**
54+
* Control cursor code list
55+
* @var array
56+
*/
57+
private static $ctrlCursorCodes = [
58+
// Hides the cursor. Use [show] to bring it back.
59+
'hide' => '?25l',
60+
61+
// Will show a cursor again when it has been hidden by [hide]
62+
'show' => '?25h',
63+
64+
// Saves the current cursor position, Position can then be restored with [restorePosition].
65+
// - 保存当前光标位置,然后可以使用[restorePosition]恢复位置
66+
'savePosition' => 's',
67+
68+
// Restores the cursor position saved with [savePosition] - 恢复[savePosition]保存的光标位置
69+
'restorePosition' => 'u',
70+
71+
// Moves the terminal cursor up
72+
'up' => '%dA',
73+
74+
// Moves the terminal cursor down
75+
'down' => '%B',
76+
77+
// Moves the terminal cursor forward - 移动终端光标前进多远
78+
'forward' => '%dC',
79+
80+
// Moves the terminal cursor backward - 移动终端光标后退多远
81+
'backward' => '%dD',
82+
83+
// Moves the terminal cursor to the beginning of the previous line - 移动终端光标到前一行的开始
84+
'prevLine' => '%dF',
85+
86+
// Moves the terminal cursor to the beginning of the next line - 移动终端光标到下一行的开始
87+
'nextLine' => '%dE',
88+
89+
// Moves the cursor to an absolute position given as column and row
90+
// $column 1-based column number, 1 is the left edge of the screen.
91+
// $row 1-based row number, 1 is the top edge of the screen. if not set, will move cursor only in current line.
92+
'coordinate' => '%dG|%d;%dH' // only column: '%dG', column and row: '%d;%dH'.
93+
];
94+
95+
/**
96+
* Control screen code list
97+
* @var array
98+
*/
99+
private static $ctrlScreenCodes = [
100+
// Clears entire screen content - 清除整个屏幕内容
101+
'clear' => '2J', // "\033[2J"
102+
103+
// Clears text from cursor to the beginning of the screen - 从光标清除文本到屏幕的开头
104+
'clearBeforeCursor' => '1J',
105+
106+
// Clears the line - 清除此行
107+
'clearLine' => '2K',
108+
109+
// Clears text from cursor position to the beginning of the line - 清除此行从光标位置开始到开始的字符
110+
'clearLineBeforeCursor' => '1K',
111+
112+
// Clears text from cursor position to the end of the line - 清除此行从光标位置开始到结束的字符
113+
'clearLineAfterCursor' => '0K',
114+
115+
// Scrolls whole page up. e.g "\033[2S" scroll up 2 line. - 上移多少行
116+
'scrollUp' => '%dS',
117+
118+
// Scrolls whole page down.e.g "\033[2T" scroll down 2 line. - 下移多少行
119+
'scrollDown' => '%dT',
120+
];
121+
122+
public static function make(): Terminal
123+
{
124+
if (!self::$instance) {
125+
self::$instance = new self;
126+
}
127+
128+
return self::$instance;
129+
}
130+
131+
/**
132+
* build ansi code string
133+
*
134+
* ```
135+
* Terminal::build(null, 'u'); // "\033[s" Saves the current cursor position
136+
* Terminal::build(0); // "\033[0m" Build end char, Resets any ANSI format
137+
* ```
138+
*
139+
* @param mixed $format
140+
* @param string $type
141+
* @return string
142+
*/
143+
public static function build($format, $type = 'm'): string
144+
{
145+
$format = null === $format ? '' : implode(';', (array)$format);
146+
147+
return "\033[" . implode(';', (array)$format) . $type;
148+
}
149+
150+
/**
151+
* control cursor
152+
* @param string $typeName
153+
* @param int $arg1
154+
* @param null $arg2
155+
* @return $this
156+
*/
157+
public function cursor($typeName, $arg1 = 1, $arg2 = null): self
158+
{
159+
if (!isset(self::$ctrlCursorCodes[$typeName])) {
160+
Cli::stderr("The [$typeName] is not supported cursor control.", true);
161+
}
162+
163+
$code = self::$ctrlCursorCodes[$typeName];
164+
165+
// allow argument
166+
if (false !== strpos($code, '%')) {
167+
// The special code: ` 'coordinate' => '%dG|%d;%dH' `
168+
if ($typeName === self::CUR_COORDINATE) {
169+
$codes = explode('|', $code);
170+
171+
if (null === $arg2) {
172+
$code = sprintf($codes[0], $arg1);
173+
} else {
174+
$code = sprintf($codes[1], $arg1, $arg2);
175+
}
176+
177+
} else {
178+
$code = sprintf($code, $arg1);
179+
}
180+
}
181+
182+
echo self::build($code, '');
183+
184+
return $this;
185+
}
186+
187+
/**
188+
* control screen
189+
* @param $typeName
190+
* @param null $arg
191+
* @return $this
192+
*/
193+
public function screen(string $typeName, $arg = null): self
194+
{
195+
if (!isset(self::$ctrlScreenCodes[$typeName])) {
196+
Cli::stderr("The [$typeName] is not supported cursor control.");
197+
}
198+
199+
$code = self::$ctrlScreenCodes[$typeName];
200+
201+
// allow argument
202+
if (false !== strpos($code, '%')) {
203+
$code = sprintf($code, $arg);
204+
}
205+
206+
echo self::build($code, '');
207+
208+
return $this;
209+
}
210+
211+
public function reset()
212+
{
213+
echo self::END_CHAR;
214+
}
215+
216+
/**
217+
* @return array
218+
*/
219+
public static function supportedCursorCtrl(): array
220+
{
221+
return \array_keys(self::$ctrlCursorCodes);
222+
}
223+
224+
/**
225+
* @return array
226+
*/
227+
public static function supportedScreenCtrl(): array
228+
{
229+
return \array_keys(self::$ctrlScreenCodes);
230+
}
231+
}

0 commit comments

Comments
 (0)