libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
terminal.hpp
1#pragma once
2
3#include <cctype>
4#include <cstddef>
5#include <cstdint>
6#include <cstdio>
7#include <cstring>
8#include <utility>
9
10#include "libxr_rw.hpp"
11#include "libxr_string.hpp"
12#include "ramfs.hpp"
13#include "semaphore.hpp"
14#include "stack.hpp"
15
16namespace LibXR
17{
18
28template <size_t READ_BUFF_SIZE = 32, size_t MAX_LINE_SIZE = READ_BUFF_SIZE,
29 size_t MAX_ARG_NUMBER = 5, size_t MAX_HISTORY_NUMBER = 5>
31{
32 private:
33 static constexpr char CLEAR_ALL[] =
34 "\033[2J\033[1H";
35 static constexpr char CLEAR_LINE[] =
36 "\033[2K\r";
37 static constexpr char CLEAR_BEHIND[] =
38 "\033[K";
39 static constexpr char KEY_RIGHT[] = "\033[C";
40 static constexpr char KEY_LEFT[] = "\033[D";
41 static constexpr char KEY_SAVE[] = "\033[s";
42 static constexpr char KEY_LOAD[] = "\033[u";
43 static constexpr char DELETE_CHAR[] =
44 "\b \b";
45
54 char *StrchrRev(char *str, char c)
55 {
56 auto len = strlen(str);
57 for (int i = static_cast<int>(len - 1); i >= 0; i--)
58 {
59 if (str[i] == c)
60 {
61 return str + i;
62 }
63 }
64 return nullptr;
65 }
66
67 public:
73 enum class Mode : uint8_t
74 {
75 CRLF = 0,
76 LF = 1,
77 CR = 2
78 };
79
93 Terminal(LibXR::RamFS &ramfs, RamFS::Dir *current_dir = nullptr,
94 ReadPort *read_port = STDIO::read_, WritePort *write_port = STDIO::write_,
96 : read_status_(ReadOperation::OperationPollingStatus::READY),
97 write_status_(WriteOperation::OperationPollingStatus::READY),
98 MODE(MODE),
99 write_op_(write_status_),
100 read_port_(read_port),
101 write_port_(write_port),
103 ramfs_(ramfs),
104 current_dir_(current_dir ? current_dir : &ramfs_.root_),
105 input_line_(MAX_LINE_SIZE + 1),
106 history_(MAX_HISTORY_NUMBER)
107 {
108 ASSERT(read_port != nullptr);
109 ASSERT(write_port != nullptr);
110 ASSERT(read_port->Readable());
111 ASSERT(write_port->Writable());
112
113 if (write_port == STDIO::write_)
114 {
115 if (STDIO::write_mutex_ == nullptr)
116 {
118 }
119
121 STDIO::write_stream_ = &write_stream_;
122 }
123 else
124 {
126 }
127 }
128
131
132 const Mode MODE;
137
139
141 char read_buff_[READ_BUFF_SIZE];
142
144 uint8_t flag_ansi_ = 0;
145 int offset_ = 0;
147 char *arg_tab_[MAX_ARG_NUMBER];
148 size_t arg_number_ = 0;
150 int history_index_ = -1;
151 bool linefeed_flag_ = false;
152
157 void LineFeed()
158 {
159 if (MODE == Mode::CRLF)
160 {
161 write_stream_ << ConstRawData("\r\n");
162 }
163 else if (MODE == Mode::LF)
164 {
166 }
167 else if (MODE == Mode::CR)
168 {
170 }
171 }
172
183
189 bool CanDisplayChar() { return input_line_.EmptySize() > 1; }
190
196 bool CanDeleteChar() { return input_line_.Size() + offset_ > 0; }
197
203 void AddCharToInputLine(char data)
204 {
205 if (offset_ == 0)
206 {
207 input_line_.Push(data);
208 }
209 else
210 {
212 }
213 input_line_[input_line_.Size()] = '\0';
214 }
215
222 void DisplayChar(char data)
223 {
224 bool use_history = false;
225
226 if (history_index_ >= 0)
227 {
229 use_history = true;
230 }
231
232 if (CanDisplayChar())
233 {
234 AddCharToInputLine(data);
235 if (use_history)
236 {
237 ShowHistory();
238 }
239 else
240 {
242 }
243 if (offset_ != 0)
244 {
246 }
247 }
248 }
249
256 {
257 if (offset_ == 0)
258 {
260 }
261 else
262 {
264 }
265 input_line_[input_line_.Size()] = '\0';
266 }
267
274 {
275 bool use_history = false;
276
277 if (history_index_ >= 0)
278 {
280 use_history = true;
281 }
282
283 if (CanDeleteChar())
284 {
286 if (use_history)
287 {
288 ShowHistory();
289 }
290 else
291 {
293 }
294
295 if (offset_ != 0)
296 {
298 }
299 }
300 }
301
307 {
308 write_stream_ << ConstRawData(ramfs_.root_->name, strlen(ramfs_.root_->name));
309 if (current_dir_ == &ramfs_.root_)
310 {
312 }
313 else
314 {
316 }
317
319 }
320
326
332
338 {
339 ClearLine();
340 ShowHeader();
341 offset_ = 0;
342 if (history_index_ >= 0)
343 {
345 history_[-history_index_ - 1].Length());
346 }
347 else
348 {
350 }
351 }
352
359 {
361 for (size_t i = 0; i < history_[-history_index_ - 1].Length(); i++)
362 {
364 }
365 history_index_ = -1;
366 offset_ = 0;
367 }
368
374 {
375 input_line_.Push('\0');
376
377 if (history_.EmptySize() == 0)
378 {
379 history_.Pop();
380 }
381 history_.Push(*reinterpret_cast<String<MAX_LINE_SIZE> *>(&input_line_[0]));
382 }
383
388 void GetArgs()
389 {
390 for (int i = 0; input_line_[i] != '\0'; i++)
391 {
392 if (input_line_[i] == ' ')
393 {
394 input_line_[i] = '\0';
395 }
396 else if (i == 0 || input_line_[i - 1] == '\0')
397 {
398 if (arg_number_ >= MAX_ARG_NUMBER)
399 {
400 return;
401 }
403 }
404 }
405 }
406
414 RamFS::Dir *Path2Dir(char *path)
415 {
416 if (path == nullptr)
417 {
418 return nullptr;
419 }
420
421 size_t index = 0;
423
424 if (*path == '/')
425 {
426 index++;
427 dir = &ramfs_.root_;
428 }
429
430 for (size_t i = 0; i < MAX_LINE_SIZE; i++)
431 {
432 auto tmp = strchr(path + index, '/');
433 if (tmp == nullptr)
434 {
435 return dir->FindDir(path + index);
436 }
437 else if (tmp == path + index)
438 {
439 return nullptr;
440 }
441 else
442 {
443 tmp[0] = '\0';
444 dir = dir->FindDir(path + index);
445 tmp[0] = '/';
446 index += tmp - path + 1;
447 if (path[index] == '\0' || dir == nullptr)
448 {
449 return dir;
450 }
451 }
452 }
453
454 return nullptr;
455 }
456
465 {
466 if (path == nullptr)
467 {
468 return nullptr;
469 }
470
471 auto name = StrchrRev(path, '/');
472
473 if (name == nullptr)
474 {
475 return current_dir_->FindFile(path);
476 }
477
478 if (name[1] == '\0')
479 {
480 return nullptr;
481 }
482
483 *name = '\0';
484 RamFS::Dir *dir = Path2Dir(path);
485 *name = '/';
486 if (dir != nullptr)
487 {
488 return dir->FindFile(name + 1);
489 }
490 else
491 {
492 return nullptr;
493 }
494 }
495
501 {
502 AddHistory();
503
504 GetArgs();
505
506 if (arg_number_ < 1 || arg_number_ > MAX_ARG_NUMBER)
507 {
508 return;
509 }
510
511 if (strcmp(arg_tab_[0], "cd") == 0)
512 {
513 RamFS::Dir *dir = Path2Dir(arg_tab_[1]);
514 if (dir != nullptr)
515 {
516 current_dir_ = dir;
517 }
518 LineFeed();
519 return;
520 }
521
522 if (strcmp(arg_tab_[0], "ls") == 0)
523 {
524 auto ls_fun = [&](RBTree<const char *>::Node<RamFS::FsNode> &item)
525 {
526 switch (item->type)
527 {
530 break;
533 break;
536 break;
539 break;
540 default:
542 break;
543 }
544 write_stream_ << ConstRawData(item.data_.name);
545 this->LineFeed();
546 return ErrorCode::OK;
547 };
548
549 current_dir_->data_.rbt.Foreach<RamFS::FsNode>(ls_fun);
550 return;
551 }
552
553 auto ans = Path2File(arg_tab_[0]);
554 if (ans == nullptr)
555 {
556 write_stream_ << ConstRawData("Command not found.");
557 LineFeed();
558 return;
559 }
560
561 if ((*ans)->type != RamFS::FileType::EXEC)
562 {
563 write_stream_ << ConstRawData("Not an executable file.");
564 LineFeed();
565 return;
566 }
569 (*ans)->Run(arg_number_, arg_tab_);
571 }
572
579 void Parse(RawData &raw_data)
580 {
581 char *buff = static_cast<char *>(raw_data.addr_);
582 for (size_t i = 0; i < raw_data.size_; i++)
583 {
584 HandleCharacter(buff[i]);
585 }
586 }
587
594 void HandleAnsiCharacter(char data)
595 {
596 if (flag_ansi_ == 1)
597 {
598 if (isprint(data))
599 {
600 flag_ansi_++;
601 }
602 else
603 {
604 flag_ansi_ = 0;
605 }
606 }
607 else if (flag_ansi_ == 2)
608 {
609 switch (data)
610 {
611 case 'A':
612 if (history_index_ < int(history_.Size()) - 1)
613 {
615 ShowHistory();
616 }
617 break;
618 case 'B':
619 if (history_index_ >= 0)
620 {
622 ShowHistory();
623 }
624 break;
625 case 'C':
626 if (history_index_ >= 0)
627 {
629 ShowHistory();
630 }
631 if (offset_ < 0)
632 {
633 offset_++;
635 }
636
637 break;
638 case 'D':
639 if (history_index_ >= 0)
640 {
642 ShowHistory();
643 }
644 if (offset_ + input_line_.Size() > 0)
645 {
646 offset_--;
648 }
649 break;
650 default:
651 break;
652 }
653
654 flag_ansi_ = 0;
655 }
656 }
657
663 {
664 /* skip space */
665 char *path = &input_line_[0];
666 while (*path == ' ')
667 {
668 path++;
669 }
670
671 /* find last '/' in first argument */
672 char *tmp = path, *path_end = path;
673
674 while (*tmp != ' ' && *tmp != '\0')
675 {
676 if (*tmp == '/')
677 {
678 path_end = tmp;
679 }
680 tmp++;
681 }
682
683 /* return if not need complete */
684 if (tmp - &input_line_[0] != static_cast<int>(input_line_.Size() + offset_))
685 {
686 return;
687 }
688
689 /* get start of prefix */
690 char *prefix_start = nullptr;
691 RamFS::Dir *dir = nullptr;
692
693 if (path_end == path)
694 {
695 dir = current_dir_;
696 prefix_start = path_end;
697 }
698 else
699 {
700 prefix_start = path_end + 1;
701 }
702
703 /* find dir*/
704 if (dir == nullptr)
705 {
706 *path_end = '\0';
707 dir = Path2Dir(path);
708 *path_end = '/';
709 if (dir == nullptr)
710 {
711 return;
712 }
713 }
714
715 /* prepre for match */
716 RBTree<const char *>::Node<RamFS::FsNode> *ans_node = nullptr;
717 uint32_t number = 0;
718 size_t same_char_number = 0;
719
720 if (*prefix_start == '/')
721 {
722 prefix_start++;
723 }
724
725 int prefix_len = static_cast<int>(tmp - prefix_start);
726
727 auto foreach_fun_find = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
728 {
729 if (strncmp(node->name, prefix_start, prefix_len) == 0)
730 {
731 ans_node = &node;
732 number++;
733 }
734
735 return ErrorCode::OK;
736 };
737
738 /* start match */
739 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_find);
740
741 if (number == 0)
742 {
743 return;
744 }
745 else if (number == 1)
746 {
747 auto name_len = strlen(ans_node->data_.name);
748 for (size_t i = 0; i < name_len - prefix_len; i++)
749 {
750 DisplayChar(ans_node->data_.name[i + prefix_len]);
751 }
752 }
753 else
754 {
755 ans_node = nullptr;
756 LineFeed();
757
758 auto foreach_fun_show = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
759 {
760 if (strncmp(node->name, prefix_start, prefix_len) == 0)
761 {
762 auto name_len = strlen(node->name);
763 write_stream_ << ConstRawData(node->name, name_len);
764 this->LineFeed();
765 if (ans_node == nullptr)
766 {
767 ans_node = &node;
768 same_char_number = name_len;
769 return ErrorCode::OK;
770 }
771
772 for (size_t i = 0; i < name_len; i++)
773 {
774 if (node->name[i] != ans_node->data_.name[i])
775 {
776 same_char_number = i;
777 break;
778 }
779 }
780
781 if (same_char_number > name_len)
782 {
783 name_len = same_char_number;
784 }
785
786 ans_node = &node;
787 }
788
789 return ErrorCode::OK;
790 };
791
792 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_show);
793
794 ShowHeader();
796
797 for (size_t i = 0; i < same_char_number - prefix_len; i++)
798 {
799 DisplayChar(ans_node->data_.name[i + prefix_len]);
800 }
801 }
802 }
803
810 {
811 if (data != '\r' && data != '\n')
812 {
813 linefeed_flag_ = false;
814 }
815
816 switch (data)
817 {
818 case '\n':
819 case '\r':
820 if (linefeed_flag_)
821 {
822 linefeed_flag_ = false;
823 return;
824 }
825 if (history_index_ >= 0)
826 {
828 }
829 LineFeed();
830 if (input_line_.Size() > 0)
831 {
833 arg_number_ = 0;
834 }
835 ShowHeader();
837 input_line_[0] = '\0';
838 offset_ = 0;
839 break;
840 case 0x7f:
841 case '\b':
842 DeleteChar();
843 break;
844 case '\t':
845 AutoComplete();
846 break;
847 case '\033':
848 flag_ansi_ = 1;
849 break;
850 default:
851 break;
852 }
853 }
854
860 void HandleCharacter(char data)
861 {
862 if (flag_ansi_)
863 {
865 }
866 else if (isprint(data))
867 {
868 DisplayChar(data);
869 }
870 else
871 {
873 }
874 }
875
892 static void ThreadFun(Terminal *term)
893 {
894 RawData buff = term->read_buff_;
895
896 Semaphore read_sem, write_sem;
897 ReadOperation op(read_sem);
898
899 term->write_op_.type = WriteOperation::OperationType::NONE;
900 term->write_op_.data.sem_info.sem = &write_sem;
901 term->write_op_.data.sem_info.timeout = 10;
902 term->write_op_.type = WriteOperation::OperationType::BLOCK;
903
904 while (true)
905 {
906 buff.size_ = LibXR::min(term->read_port_->Size(), READ_BUFF_SIZE);
907 if ((*term->read_port_)(buff, op) == ErrorCode::OK)
908 {
909 if (term->read_port_->read_size_ > 0)
910 {
911 buff.size_ = term->read_port_->read_size_;
912 term->write_mutex_->Lock();
913 term->Parse(buff);
914 term->write_stream_.Commit();
915 term->write_mutex_->Unlock();
916 }
917 }
918 }
919 }
920
936 static void TaskFun(Terminal *term)
937 {
938 RawData buff = term->read_buff_;
939 buff.size_ = LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
940
941 ReadOperation op(term->read_status_);
942
943 while (true)
944 {
945 switch (term->read_status_)
946 {
947 case ReadOperation::OperationPollingStatus::READY:
948 buff.size_ =
949 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
950 (*term->read_port_)(buff, op);
951 continue;
952 case ReadOperation::OperationPollingStatus::RUNNING:
953 return;
954 case ReadOperation::OperationPollingStatus::DONE:
955 buff.size_ = term->read_port_->read_size_;
956 if (buff.size_ > 0)
957 {
958 term->write_mutex_->Lock();
959 term->Parse(buff);
960 term->write_stream_.Commit();
961 term->write_mutex_->Unlock();
962 }
963 buff.size_ =
964 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
965 (*term->read_port_)(buff, op);
966 return;
967 }
968 }
969 }
970};
971} // namespace LibXR
常量原始数据封装类。 A class for encapsulating constant raw data.
互斥锁类,提供线程同步机制 (Mutex class providing thread synchronization mechanisms).
Definition mutex.hpp:18
ErrorCode Lock()
加锁,如果锁已被占用,则阻塞等待 (Lock the mutex, blocking if it is already locked).
Definition mutex.cpp:14
void Unlock()
解锁互斥锁 (Unlock the mutex).
Definition mutex.cpp:28
union LibXR::Operation::@5 data
OperationType type
Definition libxr_rw.hpp:226
基于 BaseQueue 的泛型队列模板类 (Generic queue template class based on BaseQueue).
Definition queue.hpp:174
红黑树的泛型数据节点,继承自 BaseNode (Generic data node for Red-Black Tree, inheriting from BaseNode).
Definition rbt.hpp:64
Data data_
存储的数据 (Stored data).
Definition rbt.hpp:99
目录类,继承自 RBTree 节点,用于管理文件、子目录和设备 Directory class, inheriting from RBTree node, used for managing files...
Definition ramfs.hpp:229
File * FindFile(const char *name)
查找当前目录中的文件 Finds a file in the current directory
Definition ramfs.cpp:32
Dir * FindDir(const char *name)
查找当前目录中的子目录 Finds a subdirectory in the current directory
Definition ramfs.cpp:82
文件系统节点基类,所有文件和目录均继承自该类 Base class for file system nodes; all files and directories inherit from this
Definition ramfs.hpp:73
轻量级的内存文件系统,实现基本的文件、目录和设备管理 A lightweight in-memory file system implementing basic file,...
Definition ramfs.hpp:20
@ STORAGE
存储 Storage
@ DIR
目录 Directory
@ EXEC
可执行 Executable
Dir root_
文件系统的根目录 Root directory of the file system
Definition ramfs.hpp:466
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ReadPort class for handling read operations.
Definition libxr_rw.hpp:269
virtual size_t Size()
获取当前队列的已使用大小。 Gets the currently used size of the queue.
Definition libxr_rw.cpp:23
static LibXR::Mutex * write_mutex_
Write port mutex. 写入端口互斥锁。
Definition libxr_rw.hpp:607
static ReadPort * read_
Read port instance. 读取端口。
Definition libxr_rw.hpp:605
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:606
信号量类,实现线程同步机制 Semaphore class implementing thread synchronization
Definition semaphore.hpp:23
线程安全的栈数据结构 / Thread-safe stack data structure
Definition stack.hpp:23
ErrorCode Delete(uint32_t index)
删除指定位置的数据 / Deletes data at a specified position
Definition stack.hpp:197
uint32_t EmptySize() const
获取栈的剩余可用空间 / Returns the remaining available space in the stack
Definition stack.hpp:68
ErrorCode Insert(const Data &data, uint32_t index)
在指定位置插入数据 / Inserts data at a specified position
Definition stack.hpp:165
void Reset()
重置栈 / Resets the stack
Definition stack.hpp:221
ErrorCode Push(const Data &data)
向栈中推入数据 / Pushes data onto the stack
Definition stack.hpp:77
ErrorCode Pop(Data &data)
从栈中弹出数据 / Pops data from the stack
Definition stack.hpp:98
uint32_t Size() const
获取栈中当前元素数量 / Returns the number of elements currently in the stack
Definition stack.hpp:63
A fixed-length string class with safe operations.
终端类,实现一个基于 RamFS 的基本命令行接口 Terminal class implementing a basic command-line interface based on RamFS
Definition terminal.hpp:31
bool CanDisplayChar()
检查是否可以显示字符 Checks if a character can be displayed
Definition terminal.hpp:189
RamFS::Dir * Path2Dir(char *path)
将路径字符串解析为目录对象 Converts a path string into a directory object
Definition terminal.hpp:414
char * arg_tab_[MAX_ARG_NUMBER]
命令参数列表 Command argument list
Definition terminal.hpp:147
void HandleAnsiCharacter(char data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:594
Queue< LibXR::String< MAX_LINE_SIZE > > history_
历史命令 History of commands
Definition terminal.hpp:149
WritePort * write_port_
写入端口 Write port
Definition terminal.hpp:135
void UpdateDisplayPosition()
更新光标位置 Updates cursor position
Definition terminal.hpp:177
static constexpr char KEY_LEFT[]
左箭头键 Left arrow key
Definition terminal.hpp:40
size_t arg_number_
参数数量 Number of arguments
Definition terminal.hpp:148
uint8_t flag_ansi_
ANSI 控制字符状态 ANSI control character state.
Definition terminal.hpp:144
Terminal(LibXR::RamFS &ramfs, RamFS::Dir *current_dir=nullptr, ReadPort *read_port=STDIO::read_, WritePort *write_port=STDIO::write_, Mode MODE=Mode::CRLF)
终端构造函数,初始化文件系统、I/O 端口和当前目录 Constructor to initialize the terminal with file system,...
Definition terminal.hpp:93
void AutoComplete()
实现命令自动补全,匹配目录或文件名 Implements command auto-completion by matching directories or file names
Definition terminal.hpp:662
void HandleCharacter(char data)
处理输入字符,根据类型调用相应的处理函数 Handles input characters, dispatching them to the appropriate handler
Definition terminal.hpp:860
void HandleControlCharacter(char data)
处理控制字符,包括换行、删除、制表符等 Handles control characters such as newline, delete, and tab
Definition terminal.hpp:809
ReadPort * read_port_
读取端口 Read port
Definition terminal.hpp:134
WriteOperation write_op_
终端写操作 Terminal write operation
Definition terminal.hpp:133
bool CanDeleteChar()
检查是否可以删除字符 Checks if a character can be deleted
Definition terminal.hpp:196
static constexpr char KEY_LOAD[]
恢复光标位置 Restore cursor position
Definition terminal.hpp:42
char read_buff_[READ_BUFF_SIZE]
读取缓冲区 Read buffer
Definition terminal.hpp:141
int history_index_
当前历史索引 Current history index
Definition terminal.hpp:150
RamFS & ramfs_
关联的文件系统 Associated file system
Definition terminal.hpp:140
WritePort::Stream write_stream_
写入流 Write stream
Definition terminal.hpp:136
char * StrchrRev(char *str, char c)
反向查找字符串中的特定字符 Finds a specific character in a string from the end
Definition terminal.hpp:54
int offset_
光标偏移 Cursor offset
Definition terminal.hpp:145
void ClearLine()
清除当前行 Clears the current line
Definition terminal.hpp:325
LibXR::Mutex * write_mutex_
写入端口互斥锁 Write port mutex
Definition terminal.hpp:138
void CopyHistoryToInputLine()
将历史命令复制到输入行,并重置历史索引和光标偏移 Copies the history command to the input line and resets history index and cu...
Definition terminal.hpp:358
void AddHistory()
将当前输入行添加到历史记录 Adds the current input line to the history
Definition terminal.hpp:373
void DisplayChar(char data)
在终端上显示字符,并根据历史记录模式进行相应操作 Displays a character on the terminal and updates accordingly if history mode...
Definition terminal.hpp:222
RamFS::File * Path2File(char *path)
将路径字符串解析为文件对象 Converts a path string into a file object
Definition terminal.hpp:464
static constexpr char CLEAR_LINE[]
清除当前行命令 Clear current line command
Definition terminal.hpp:35
void ShowHistory()
显示历史记录中的输入行,更新终端显示 Displays the input line from history and updates the terminal display
Definition terminal.hpp:337
static constexpr char DELETE_CHAR[]
退格删除字符 Backspace delete character
Definition terminal.hpp:43
static constexpr char CLEAR_ALL[]
清屏命令 Clear screen command
Definition terminal.hpp:33
void LineFeed()
执行换行操作 Performs a line feed operation
Definition terminal.hpp:157
void Clear()
清除整个终端屏幕 Clears the entire terminal screen
Definition terminal.hpp:331
void RemoveCharFromInputLine()
从输入行中删除字符,支持在光标位置删除 Removes a character from the input line, supports deletion at the cursor position
Definition terminal.hpp:255
static constexpr char CLEAR_BEHIND[]
清除光标后内容命令 Clear content after cursor command
Definition terminal.hpp:37
static void TaskFun(Terminal *term)
终端任务函数,以定时器任务方式驱动终端 Terminal task function, drives the terminal using a scheduled task
Definition terminal.hpp:936
void GetArgs()
解析输入行,将其拆分为参数数组 Parses the input line and splits it into argument array
Definition terminal.hpp:388
void Parse(RawData &raw_data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:579
void ShowHeader()
显示终端提示符,包括当前目录信息 Displays the terminal prompt, including the current directory information
Definition terminal.hpp:306
RamFS::Dir * current_dir_
当前目录 Current directory
Definition terminal.hpp:143
Stack< char > input_line_
输入行缓冲区 Input line buffer
Definition terminal.hpp:146
static constexpr char KEY_SAVE[]
保存光标位置 Save cursor position
Definition terminal.hpp:41
static void ThreadFun(Terminal *term)
终端线程函数,以独立线程方式持续驱动终端 Terminal thread function, continuously drives the terminal as an independent thr...
Definition terminal.hpp:892
void ExecuteCommand()
解析并执行输入的命令 Parses and executes the entered command
Definition terminal.hpp:500
void DeleteChar()
处理删除字符操作,支持回退删除,并在历史模式下更新显示 Handles the delete character operation, supports backspace deletion,...
Definition terminal.hpp:273
Mode
终端换行模式 Line feed modes for the terminal
Definition terminal.hpp:74
@ CR
仅回车 Carriage Return (\r)
@ CRLF
回车换行 Carriage Return + Line Feed (\r )
@ LF
仅换行 Line Feed ( )
bool linefeed_flag_
换行标志 Line feed flag
Definition terminal.hpp:151
const Mode MODE
终端换行模式 Terminal line feed mode
Definition terminal.hpp:132
static constexpr char KEY_RIGHT[]
右箭头键 Right arrow key
Definition terminal.hpp:39
void AddCharToInputLine(char data)
向输入行中添加字符,支持在光标位置插入 Adds a character to the input line, supports insertion at the cursor position
Definition terminal.hpp:203
WritePort 的流式写入操作器,支持链式 << 操作和批量提交。
Definition libxr_rw.hpp:432
ErrorCode Commit()
手动提交已写入的数据到队列,并尝试续锁。
Definition libxr_rw.cpp:417
WritePort class for handling write operations.
Definition libxr_rw.hpp:406
LibXR 命名空间
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值
constexpr auto min(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最小值