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
90 Terminal(LibXR::RamFS &ramfs, RamFS::Dir *current_dir = nullptr,
91 ReadPort *read_port = STDIO::read_, WritePort *write_port = STDIO::write_,
93 : read_status_(ReadOperation::OperationPollingStatus::READY),
94 write_status_(WriteOperation::OperationPollingStatus::READY),
95 MODE(MODE),
96 write_op_(write_status_),
97 read_(read_port),
98 write_(write_port),
99 ramfs_(ramfs),
100 current_dir_(current_dir ? current_dir : &ramfs_.root_),
101 input_line_(MAX_LINE_SIZE + 1),
102 history_(MAX_HISTORY_NUMBER)
103 {
104 ASSERT(read_port != nullptr);
105 ASSERT(write_port != nullptr);
106 ASSERT(read_port->Readable());
107 ASSERT(write_port->Writable());
108 }
109
112
113 const Mode MODE;
118 char read_buff_[READ_BUFF_SIZE];
119
121 uint8_t flag_ansi_ = 0;
122 int offset_ = 0;
124 char *arg_tab_[MAX_ARG_NUMBER];
125 size_t arg_number_ = 0;
127 int history_index_ = -1;
128 bool linefeed_flag_ = false;
129
134 void LineFeed()
135 {
136 if (MODE == Mode::CRLF)
137 {
138 (*write_)(ConstRawData("\r\n"), write_op_);
139 }
140 else if (MODE == Mode::LF)
141 {
142 (*write_)(ConstRawData('\n'), write_op_);
143 }
144 else if (MODE == Mode::CR)
145 {
146 (*write_)(ConstRawData('\r'), write_op_);
147 }
148 }
149
155 {
156 (*write_)(ConstRawData(KEY_SAVE), write_op_);
159 write_op_);
160 (*write_)(ConstRawData(KEY_LOAD), write_op_);
161 }
162
168 bool CanDisplayChar() { return input_line_.EmptySize() > 1; }
169
175 bool CanDeleteChar() { return input_line_.Size() + offset_ > 0; }
176
182 void AddCharToInputLine(char data)
183 {
184 if (offset_ == 0)
185 {
186 input_line_.Push(data);
187 }
188 else
189 {
191 }
192 input_line_[input_line_.Size()] = '\0';
193 }
194
201 void DisplayChar(char data)
202 {
203 bool use_history = false;
204
205 if (history_index_ >= 0)
206 {
208 use_history = true;
209 }
210
211 if (CanDisplayChar())
212 {
213 AddCharToInputLine(data);
214 if (use_history)
215 {
216 ShowHistory();
217 }
218 else
219 {
221 }
222 if (offset_ != 0)
223 {
225 }
226 }
227 }
228
235 {
236 if (offset_ == 0)
237 {
239 }
240 else
241 {
243 }
244 input_line_[input_line_.Size()] = '\0';
245 }
246
253 {
254 bool use_history = false;
255
256 if (history_index_ >= 0)
257 {
259 use_history = true;
260 }
261
262 if (CanDeleteChar())
263 {
265 if (use_history)
266 {
267 ShowHistory();
268 }
269 else
270 {
272 }
273
274 if (offset_ != 0)
275 {
277 }
278 }
279 }
280
286 {
287 (*write_)(ConstRawData(ramfs_.root_->name, strlen(ramfs_.root_->name)), write_op_);
288 if (current_dir_ == &ramfs_.root_)
289 {
290 (*write_)(ConstRawData(":/"), write_op_);
291 }
292 else
293 {
294 (*write_)(ConstRawData(":"), write_op_);
295 (*write_)(ConstRawData(current_dir_->data_.name), write_op_);
296 }
297
298 (*write_)(ConstRawData("$ "), write_op_);
299 }
300
306
311 void Clear() { (*write_)(ConstRawData(CLEAR_ALL), write_op_); }
312
318 {
319 ClearLine();
320 ShowHeader();
321 offset_ = 0;
322 if (history_index_ >= 0)
323 {
324 (*write_)(ConstRawData(history_[-history_index_ - 1].Raw(),
325 history_[-history_index_ - 1].Length()),
326 write_op_);
327 }
328 else
329 {
331 }
332 }
333
340 {
342 for (size_t i = 0; i < history_[-history_index_ - 1].Length(); i++)
343 {
345 }
346 history_index_ = -1;
347 offset_ = 0;
348 }
349
355 {
356 input_line_.Push('\0');
357
358 if (history_.EmptySize() == 0)
359 {
360 history_.Pop();
361 }
362 history_.Push(*reinterpret_cast<String<MAX_LINE_SIZE> *>(&input_line_[0]));
363 }
364
369 void GetArgs()
370 {
371 for (int i = 0; input_line_[i] != '\0'; i++)
372 {
373 if (input_line_[i] == ' ')
374 {
375 input_line_[i] = '\0';
376 }
377 else if (i == 0 || input_line_[i - 1] == '\0')
378 {
379 if (arg_number_ >= MAX_ARG_NUMBER)
380 {
381 return;
382 }
384 }
385 }
386 }
387
395 RamFS::Dir *Path2Dir(char *path)
396 {
397 size_t index = 0;
399
400 if (*path == '/')
401 {
402 index++;
403 dir = &ramfs_.root_;
404 }
405
406 for (size_t i = 0; i < MAX_LINE_SIZE; i++)
407 {
408 auto tmp = strchr(path + index, '/');
409 if (tmp == nullptr)
410 {
411 return dir->FindDir(path + index);
412 }
413 else if (tmp == path + index)
414 {
415 return nullptr;
416 }
417 else
418 {
419 tmp[0] = '\0';
420 dir = dir->FindDir(path + index);
421 tmp[0] = '/';
422 index += tmp - path + 1;
423 if (path[index] == '\0' || dir == nullptr)
424 {
425 return dir;
426 }
427 }
428 }
429
430 return nullptr;
431 }
432
441 {
442 auto name = StrchrRev(path, '/');
443
444 if (name == nullptr)
445 {
446 return current_dir_->FindFile(path);
447 }
448
449 if (name[1] == '\0')
450 {
451 return nullptr;
452 }
453
454 *name = '\0';
455 RamFS::Dir *dir = Path2Dir(path);
456 *name = '/';
457 if (dir != nullptr)
458 {
459 return dir->FindFile(name + 1);
460 }
461 else
462 {
463 return nullptr;
464 }
465 }
466
472 {
473 AddHistory();
474
475 GetArgs();
476
477 if (arg_number_ < 1 || arg_number_ > MAX_ARG_NUMBER)
478 {
479 return;
480 }
481
482 if (strcmp(arg_tab_[0], "cd") == 0)
483 {
484 RamFS::Dir *dir = Path2Dir(arg_tab_[1]);
485 if (dir != nullptr)
486 {
487 current_dir_ = dir;
488 }
489 LineFeed();
490 return;
491 }
492
493 if (strcmp(arg_tab_[0], "ls") == 0)
494 {
495 auto ls_fun = [&](RBTree<const char *>::Node<RamFS::FsNode> &item)
496 {
497 switch (item->type)
498 {
500 (*(this->write_))(ConstRawData("d "), this->write_op_);
501 break;
503 (*(this->write_))(ConstRawData("f "), this->write_op_);
504 break;
506 (*(this->write_))(ConstRawData("c "), this->write_op_);
507 break;
509 (*(this->write_))(ConstRawData("b "), this->write_op_);
510 break;
511 default:
512 (*(this->write_))(ConstRawData("? "), this->write_op_);
513 break;
514 }
515 (*(this->write_))(ConstRawData(item.data_.name), this->write_op_);
516 this->LineFeed();
517 return ErrorCode::OK;
518 };
519
520 current_dir_->data_.rbt.Foreach<RamFS::FsNode>(ls_fun);
521 return;
522 }
523
524 auto ans = Path2File(arg_tab_[0]);
525 if (ans == nullptr)
526 {
527 (*write_)(ConstRawData("Command not found."), write_op_);
528 LineFeed();
529 return;
530 }
531
532 if ((*ans)->type != RamFS::FileType::EXEC)
533 {
534 (*write_)(ConstRawData("Not an executable file."), write_op_);
535 LineFeed();
536 return;
537 }
538
539 (*ans)->Run(arg_number_, arg_tab_);
540 }
541
548 void Parse(RawData &raw_data)
549 {
550 char *buff = static_cast<char *>(raw_data.addr_);
551 for (size_t i = 0; i < raw_data.size_; i++)
552 {
553 HandleCharacter(buff[i]);
554 }
555 }
556
563 void HandleAnsiCharacter(char data)
564 {
565 if (flag_ansi_ == 1)
566 {
567 if (isprint(data))
568 {
569 flag_ansi_++;
570 }
571 else
572 {
573 flag_ansi_ = 0;
574 }
575 }
576 else if (flag_ansi_ == 2)
577 {
578 switch (data)
579 {
580 case 'A':
581 if (history_index_ < int(history_.Size()) - 1)
582 {
584 ShowHistory();
585 }
586 break;
587 case 'B':
588 if (history_index_ >= 0)
589 {
591 ShowHistory();
592 }
593 break;
594 case 'C':
595 if (history_index_ >= 0)
596 {
598 ShowHistory();
599 }
600 if (offset_ < 0)
601 {
602 offset_++;
603 (*write_)(ConstRawData(KEY_RIGHT, sizeof(KEY_RIGHT) - 1), write_op_);
604 }
605
606 break;
607 case 'D':
608 if (history_index_ >= 0)
609 {
611 ShowHistory();
612 }
613 if (offset_ + input_line_.Size() > 0)
614 {
615 offset_--;
616 (*write_)(ConstRawData(KEY_LEFT, sizeof(KEY_LEFT) - 1), write_op_);
617 }
618 break;
619 default:
620 break;
621 }
622
623 flag_ansi_ = 0;
624 }
625 }
626
632 {
633 /* skip space */
634 char *path = &input_line_[0];
635 while (*path == ' ')
636 {
637 path++;
638 }
639
640 /* find last '/' in first argument */
641 char *tmp = path, *path_end = path;
642
643 while (*tmp != ' ' && *tmp != '\0')
644 {
645 if (*tmp == '/')
646 {
647 path_end = tmp;
648 }
649 tmp++;
650 }
651
652 /* return if not need complete */
653 if (tmp - &input_line_[0] != static_cast<int>(input_line_.Size() + offset_))
654 {
655 return;
656 }
657
658 /* get start of prefix */
659 char *prefix_start = nullptr;
660 RamFS::Dir *dir = nullptr;
661
662 if (path_end == path)
663 {
664 dir = current_dir_;
665 prefix_start = path_end;
666 }
667 else
668 {
669 prefix_start = path_end + 1;
670 }
671
672 /* find dir*/
673 if (dir == nullptr)
674 {
675 *path_end = '\0';
676 dir = Path2Dir(path);
677 *path_end = '/';
678 if (dir == nullptr)
679 {
680 return;
681 }
682 }
683
684 /* prepre for match */
685 RBTree<const char *>::Node<RamFS::FsNode> *ans_node = nullptr;
686 uint32_t number = 0;
687 size_t same_char_number = 0;
688
689 if (*prefix_start == '/')
690 {
691 prefix_start++;
692 }
693
694 int prefix_len = static_cast<int>(tmp - prefix_start);
695
696 auto foreach_fun_find = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
697 {
698 if (strncmp(node->name, prefix_start, prefix_len) == 0)
699 {
700 ans_node = &node;
701 number++;
702 }
703
704 return ErrorCode::OK;
705 };
706
707 /* start match */
708 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_find);
709
710 if (number == 0)
711 {
712 return;
713 }
714 else if (number == 1)
715 {
716 auto name_len = strlen(ans_node->data_.name);
717 for (size_t i = 0; i < name_len - prefix_len; i++)
718 {
719 DisplayChar(ans_node->data_.name[i + prefix_len]);
720 }
721 }
722 else
723 {
724 ans_node = nullptr;
725 LineFeed();
726
727 auto foreach_fun_show = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
728 {
729 if (strncmp(node->name, prefix_start, prefix_len) == 0)
730 {
731 auto name_len = strlen(node->name);
732 (*this->write_)(ConstRawData(node->name, name_len), this->write_op_);
733 this->LineFeed();
734 if (ans_node == nullptr)
735 {
736 ans_node = &node;
737 same_char_number = name_len;
738 return ErrorCode::OK;
739 }
740
741 for (size_t i = 0; i < name_len; i++)
742 {
743 if (node->name[i] != ans_node->data_.name[i])
744 {
745 same_char_number = i;
746 break;
747 }
748 }
749
750 if (same_char_number > name_len)
751 {
752 name_len = same_char_number;
753 }
754
755 ans_node = &node;
756 }
757
758 return ErrorCode::OK;
759 };
760
761 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_show);
762
763 ShowHeader();
765
766 for (size_t i = 0; i < same_char_number - prefix_len; i++)
767 {
768 DisplayChar(ans_node->data_.name[i + prefix_len]);
769 }
770 }
771 }
772
779 {
780 if (data != '\r' && data != '\n')
781 {
782 linefeed_flag_ = false;
783 }
784
785 switch (data)
786 {
787 case '\n':
788 case '\r':
789 if (linefeed_flag_)
790 {
791 linefeed_flag_ = false;
792 return;
793 }
794 if (history_index_ >= 0)
795 {
797 }
798 LineFeed();
799 if (input_line_.Size() > 0)
800 {
802 arg_number_ = 0;
803 }
804 ShowHeader();
806 input_line_[0] = '\0';
807 offset_ = 0;
808 break;
809 case 0x7f:
810 case '\b':
811 DeleteChar();
812 break;
813 case '\t':
814 AutoComplete();
815 break;
816 case '\033':
817 flag_ansi_ = 1;
818 break;
819 default:
820 break;
821 }
822 }
823
829 void HandleCharacter(char data)
830 {
831 if (flag_ansi_)
832 {
834 }
835 else if (isprint(data))
836 {
837 DisplayChar(data);
838 }
839 else
840 {
842 }
843 }
844
861 static void ThreadFun(Terminal *term)
862 {
863 RawData buff = term->read_buff_;
864
865 Semaphore read_sem, write_sem;
866 ReadOperation op(read_sem);
867
868 term->write_op_.type = WriteOperation::OperationType::NONE;
869 term->write_op_.data.sem_info.sem = &write_sem;
870 term->write_op_.data.sem_info.timeout = 10;
871 term->write_op_.type = WriteOperation::OperationType::BLOCK;
872
873 while (true)
874 {
875 buff.size_ = LibXR::min(term->read_->Size(), READ_BUFF_SIZE);
876 if ((*term->read_)(buff, op) == ErrorCode::OK)
877 {
878 if (term->read_->read_size_ > 0)
879 {
880 buff.size_ = term->read_->read_size_;
881 term->Parse(buff);
882 }
883 }
884 }
885 }
886
902 static void TaskFun(Terminal *term)
903 {
904 RawData buff = term->read_buff_;
905 buff.size_ = LibXR::min(LibXR::max(1u, term->read_->Size()), READ_BUFF_SIZE);
906
907 ReadOperation op(term->read_status_);
908
909 while (true)
910 {
911 switch (term->read_status_)
912 {
913 case ReadOperation::OperationPollingStatus::READY:
914 buff.size_ = LibXR::min(LibXR::max(1u, term->read_->Size()), READ_BUFF_SIZE);
915 (*term->read_)(buff, op);
916 continue;
917 case ReadOperation::OperationPollingStatus::RUNNING:
918 return;
919 case ReadOperation::OperationPollingStatus::DONE:
920 buff.size_ = term->read_->read_size_;
921 if (buff.size_ > 0)
922 {
923 term->Parse(buff);
924 }
925 buff.size_ = LibXR::min(LibXR::max(1u, term->read_->Size()), READ_BUFF_SIZE);
926 (*term->read_)(buff, op);
927 return;
928 }
929 }
930 }
931};
932} // namespace LibXR
常量原始数据封装类。 A class for encapsulating constant raw data.
union LibXR::Operation::@4 data
OperationType type
Definition libxr_rw.hpp:227
基于 BaseQueue 的泛型队列模板类 (Generic queue template class based on BaseQueue).
Definition queue.hpp:362
红黑树的泛型数据节点,继承自 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:250
Dir * FindDir(const char *name)
查找当前目录中的子目录 Finds a subdirectory in the current directory
Definition ramfs.hpp:353
File * FindFile(const char *name)
查找当前目录中的文件 Finds a file in the current directory
Definition ramfs.hpp:290
文件系统节点基类,所有文件和目录均继承自该类 Base class for file system nodes; all files and directories inherit from this
Definition ramfs.hpp:81
轻量级的内存文件系统,实现基本的文件、目录和设备管理 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:624
原始数据封装类。 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:270
virtual size_t Size()
获取当前队列的已使用大小。 Gets the currently used size of the queue.
Definition libxr_rw.hpp:325
static ReadPort * read_
Read port instance. 读取端口。
Definition libxr_rw.hpp:821
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:822
信号量类,实现线程同步机制 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:194
uint32_t EmptySize() const
获取栈的剩余可用空间 / Returns the remaining available space in the stack
Definition stack.hpp:65
ErrorCode Insert(const Data &data, uint32_t index)
在指定位置插入数据 / Inserts data at a specified position
Definition stack.hpp:162
void Reset()
重置栈 / Resets the stack
Definition stack.hpp:218
ErrorCode Push(const Data &data)
向栈中推入数据 / Pushes data onto the stack
Definition stack.hpp:74
ErrorCode Pop(Data &data)
从栈中弹出数据 / Pops data from the stack
Definition stack.hpp:95
uint32_t Size() const
获取栈中当前元素数量 / Returns the number of elements currently in the stack
Definition stack.hpp:60
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:168
RamFS::Dir * Path2Dir(char *path)
将路径字符串解析为目录对象 Converts a path string into a directory object
Definition terminal.hpp:395
char * arg_tab_[MAX_ARG_NUMBER]
命令参数列表 Command argument list
Definition terminal.hpp:124
void HandleAnsiCharacter(char data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:563
Queue< LibXR::String< MAX_LINE_SIZE > > history_
历史命令 History of commands
Definition terminal.hpp:126
void UpdateDisplayPosition()
更新光标位置 Updates cursor position
Definition terminal.hpp:154
static constexpr char KEY_LEFT[]
左箭头键 Left arrow key
Definition terminal.hpp:40
size_t arg_number_
参数数量 Number of arguments
Definition terminal.hpp:125
uint8_t flag_ansi_
ANSI 控制字符状态 ANSI control character state.
Definition terminal.hpp:121
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:90
void AutoComplete()
实现命令自动补全,匹配目录或文件名 Implements command auto-completion by matching directories or file names
Definition terminal.hpp:631
void HandleCharacter(char data)
处理输入字符,根据类型调用相应的处理函数 Handles input characters, dispatching them to the appropriate handler
Definition terminal.hpp:829
void HandleControlCharacter(char data)
处理控制字符,包括换行、删除、制表符等 Handles control characters such as newline, delete, and tab
Definition terminal.hpp:778
WriteOperation write_op_
终端写操作 Terminal write operation
Definition terminal.hpp:114
bool CanDeleteChar()
检查是否可以删除字符 Checks if a character can be deleted
Definition terminal.hpp:175
static constexpr char KEY_LOAD[]
恢复光标位置 Restore cursor position
Definition terminal.hpp:42
char read_buff_[READ_BUFF_SIZE]
读取缓冲区 Read buffer
Definition terminal.hpp:118
int history_index_
当前历史索引 Current history index
Definition terminal.hpp:127
RamFS & ramfs_
关联的文件系统 Associated file system
Definition terminal.hpp:117
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:122
void ClearLine()
清除当前行 Clears the current line
Definition terminal.hpp:305
void CopyHistoryToInputLine()
将历史命令复制到输入行,并重置历史索引和光标偏移 Copies the history command to the input line and resets history index and cu...
Definition terminal.hpp:339
void AddHistory()
将当前输入行添加到历史记录 Adds the current input line to the history
Definition terminal.hpp:354
void DisplayChar(char data)
在终端上显示字符,并根据历史记录模式进行相应操作 Displays a character on the terminal and updates accordingly if history mode...
Definition terminal.hpp:201
ReadPort * read_
读取端口 Read port
Definition terminal.hpp:115
RamFS::File * Path2File(char *path)
将路径字符串解析为文件对象 Converts a path string into a file object
Definition terminal.hpp:440
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:317
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:134
void Clear()
清除整个终端屏幕 Clears the entire terminal screen
Definition terminal.hpp:311
void RemoveCharFromInputLine()
从输入行中删除字符,支持在光标位置删除 Removes a character from the input line, supports deletion at the cursor position
Definition terminal.hpp:234
WritePort * write_
写入端口 Write port
Definition terminal.hpp:116
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:902
void GetArgs()
解析输入行,将其拆分为参数数组 Parses the input line and splits it into argument array
Definition terminal.hpp:369
void Parse(RawData &raw_data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:548
void ShowHeader()
显示终端提示符,包括当前目录信息 Displays the terminal prompt, including the current directory information
Definition terminal.hpp:285
RamFS::Dir * current_dir_
当前目录 Current directory
Definition terminal.hpp:120
Stack< char > input_line_
输入行缓冲区 Input line buffer
Definition terminal.hpp:123
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:861
void ExecuteCommand()
解析并执行输入的命令 Parses and executes the entered command
Definition terminal.hpp:471
void DeleteChar()
处理删除字符操作,支持回退删除,并在历史模式下更新显示 Handles the delete character operation, supports backspace deletion,...
Definition terminal.hpp:252
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:128
const Mode MODE
终端换行模式 Terminal line feed mode
Definition terminal.hpp:113
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:182
WritePort class for handling write operations.
Definition libxr_rw.hpp:564
LibXR 命名空间
Definition ch32_gpio.hpp:9
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
计算两个数的最小值