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
143 size_t request_read_size_ = 0;
145 uint8_t flag_ansi_ = 0;
146 int offset_ = 0;
148 char* arg_tab_[MAX_ARG_NUMBER];
149 size_t arg_number_ = 0;
151 int history_index_ = -1;
152 bool linefeed_flag_ = false;
153
158 void LineFeed()
159 {
160 if (MODE == Mode::CRLF)
161 {
162 write_stream_ << ConstRawData("\r\n");
163 }
164 else if (MODE == Mode::LF)
165 {
167 }
168 else if (MODE == Mode::CR)
169 {
171 }
172 }
173
184
190 bool CanDisplayChar() { return input_line_.EmptySize() > 1; }
191
197 bool CanDeleteChar() { return input_line_.Size() + offset_ > 0; }
198
204 void AddCharToInputLine(char data)
205 {
206 if (offset_ == 0)
207 {
208 input_line_.Push(data);
209 }
210 else
211 {
213 }
214 input_line_[input_line_.Size()] = '\0';
215 }
216
223 void DisplayChar(char data)
224 {
225 bool use_history = false;
226
227 if (history_index_ >= 0)
228 {
230 use_history = true;
231 }
232
233 if (CanDisplayChar())
234 {
235 AddCharToInputLine(data);
236 if (use_history)
237 {
238 ShowHistory();
239 }
240 else
241 {
243 }
244 if (offset_ != 0)
245 {
247 }
248 }
249 }
250
257 {
258 if (offset_ == 0)
259 {
261 }
262 else
263 {
265 }
266 input_line_[input_line_.Size()] = '\0';
267 }
268
275 {
276 bool use_history = false;
277
278 if (history_index_ >= 0)
279 {
281 use_history = true;
282 }
283
284 if (CanDeleteChar())
285 {
287 if (use_history)
288 {
289 ShowHistory();
290 }
291 else
292 {
294 }
295
296 if (offset_ != 0)
297 {
299 }
300 }
301 }
302
308 {
309 write_stream_ << ConstRawData(ramfs_.root_->name, strlen(ramfs_.root_->name));
310 if (current_dir_ == &ramfs_.root_)
311 {
313 }
314 else
315 {
317 }
318
320 }
321
327
333
339 {
340 ClearLine();
341 ShowHeader();
342 offset_ = 0;
343 if (history_index_ >= 0)
344 {
346 history_[-history_index_ - 1].Length());
347 }
348 else
349 {
351 }
352 }
353
360 {
362 for (size_t i = 0; i < history_[-history_index_ - 1].Length(); i++)
363 {
365 }
366 history_index_ = -1;
367 offset_ = 0;
368 }
369
375 {
376 input_line_.Push('\0');
377
378 if (history_.EmptySize() == 0)
379 {
380 history_.Pop();
381 }
382 history_.Push(*reinterpret_cast<String<MAX_LINE_SIZE>*>(&input_line_[0]));
383 }
384
389 void GetArgs()
390 {
391 for (int i = 0; input_line_[i] != '\0'; i++)
392 {
393 if (input_line_[i] == ' ')
394 {
395 input_line_[i] = '\0';
396 }
397 else if (i == 0 || input_line_[i - 1] == '\0')
398 {
399 if (arg_number_ >= MAX_ARG_NUMBER)
400 {
401 return;
402 }
404 }
405 }
406 }
407
415 RamFS::Dir* Path2Dir(char* path)
416 {
417 if (path == nullptr)
418 {
419 return nullptr;
420 }
421
422 size_t index = 0;
424
425 if (*path == '/')
426 {
427 index++;
428 dir = &ramfs_.root_;
429 }
430
431 for (size_t i = 0; i < MAX_LINE_SIZE; i++)
432 {
433 auto tmp = strchr(path + index, '/');
434 if (tmp == nullptr)
435 {
436 return dir->FindDir(path + index);
437 }
438 else if (tmp == path + index)
439 {
440 return nullptr;
441 }
442 else
443 {
444 tmp[0] = '\0';
445 dir = dir->FindDir(path + index);
446 tmp[0] = '/';
447 index += tmp - path + 1;
448 if (path[index] == '\0' || dir == nullptr)
449 {
450 return dir;
451 }
452 }
453 }
454
455 return nullptr;
456 }
457
466 {
467 if (path == nullptr)
468 {
469 return nullptr;
470 }
471
472 auto name = StrchrRev(path, '/');
473
474 if (name == nullptr)
475 {
476 return current_dir_->FindFile(path);
477 }
478
479 if (name[1] == '\0')
480 {
481 return nullptr;
482 }
483
484 *name = '\0';
485 RamFS::Dir* dir = Path2Dir(path);
486 *name = '/';
487 if (dir != nullptr)
488 {
489 return dir->FindFile(name + 1);
490 }
491 else
492 {
493 return nullptr;
494 }
495 }
496
502 {
503 AddHistory();
504
505 GetArgs();
506
507 if (arg_number_ < 1 || arg_number_ > MAX_ARG_NUMBER)
508 {
509 return;
510 }
511
512 if (strcmp(arg_tab_[0], "cd") == 0)
513 {
514 RamFS::Dir* dir = Path2Dir(arg_tab_[1]);
515 if (dir != nullptr)
516 {
517 current_dir_ = dir;
518 }
519 LineFeed();
520 return;
521 }
522
523 if (strcmp(arg_tab_[0], "ls") == 0)
524 {
525 auto ls_fun = [&](RBTree<const char*>::Node<RamFS::FsNode>& item)
526 {
527 switch (item->type)
528 {
531 break;
534 break;
537 break;
540 break;
541 default:
543 break;
544 }
545 write_stream_ << ConstRawData(item.data_.name);
546 this->LineFeed();
547 return ErrorCode::OK;
548 };
549
550 current_dir_->data_.rbt.Foreach<RamFS::FsNode>(ls_fun);
551 return;
552 }
553
554 auto ans = Path2File(arg_tab_[0]);
555 if (ans == nullptr)
556 {
557 write_stream_ << ConstRawData("Command not found.");
558 LineFeed();
559 return;
560 }
561
562 if ((*ans)->type != RamFS::FileType::EXEC)
563 {
564 write_stream_ << ConstRawData("Not an executable file.");
565 LineFeed();
566 return;
567 }
570 (*ans)->Run(arg_number_, arg_tab_);
572 }
573
580 void Parse(RawData& raw_data)
581 {
582 char* buff = static_cast<char*>(raw_data.addr_);
583 for (size_t i = 0; i < raw_data.size_; i++)
584 {
585 HandleCharacter(buff[i]);
586 }
587 }
588
595 void HandleAnsiCharacter(char data)
596 {
597 if (flag_ansi_ == 1)
598 {
599 if (isprint(data))
600 {
601 flag_ansi_++;
602 }
603 else
604 {
605 flag_ansi_ = 0;
606 }
607 }
608 else if (flag_ansi_ == 2)
609 {
610 switch (data)
611 {
612 case 'A':
613 if (history_index_ < int(history_.Size()) - 1)
614 {
616 ShowHistory();
617 }
618 break;
619 case 'B':
620 if (history_index_ >= 0)
621 {
623 ShowHistory();
624 }
625 break;
626 case 'C':
627 if (history_index_ >= 0)
628 {
630 ShowHistory();
631 }
632 if (offset_ < 0)
633 {
634 offset_++;
636 }
637
638 break;
639 case 'D':
640 if (history_index_ >= 0)
641 {
643 ShowHistory();
644 }
645 if (offset_ + input_line_.Size() > 0)
646 {
647 offset_--;
649 }
650 break;
651 default:
652 break;
653 }
654
655 flag_ansi_ = 0;
656 }
657 }
658
664 {
665 /* skip space */
666 char* path = &input_line_[0];
667 while (*path == ' ')
668 {
669 path++;
670 }
671
672 /* find last '/' in first argument */
673 char *tmp = path, *path_end = path;
674
675 while (*tmp != ' ' && *tmp != '\0')
676 {
677 if (*tmp == '/')
678 {
679 path_end = tmp;
680 }
681 tmp++;
682 }
683
684 /* return if not need complete */
685 if (tmp - &input_line_[0] != static_cast<int>(input_line_.Size() + offset_))
686 {
687 return;
688 }
689
690 /* get start of prefix */
691 char* prefix_start = nullptr;
692 RamFS::Dir* dir = nullptr;
693
694 if (path_end == path)
695 {
696 dir = current_dir_;
697 prefix_start = path_end;
698 }
699 else
700 {
701 prefix_start = path_end + 1;
702 }
703
704 /* find dir*/
705 if (dir == nullptr)
706 {
707 *path_end = '\0';
708 dir = Path2Dir(path);
709 *path_end = '/';
710 if (dir == nullptr)
711 {
712 return;
713 }
714 }
715
716 /* prepre for match */
717 RBTree<const char*>::Node<RamFS::FsNode>* ans_node = nullptr;
718 uint32_t number = 0;
719 size_t same_char_number = 0;
720
721 if (*prefix_start == '/')
722 {
723 prefix_start++;
724 }
725
726 int prefix_len = static_cast<int>(tmp - prefix_start);
727
728 auto foreach_fun_find = [&](RBTree<const char*>::Node<RamFS::FsNode>& node)
729 {
730 if (strncmp(node->name, prefix_start, prefix_len) == 0)
731 {
732 ans_node = &node;
733 number++;
734 }
735
736 return ErrorCode::OK;
737 };
738
739 /* start match */
740 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_find);
741
742 if (number == 0)
743 {
744 return;
745 }
746 else if (number == 1)
747 {
748 auto name_len = strlen(ans_node->data_.name);
749 for (size_t i = 0; i < name_len - prefix_len; i++)
750 {
751 DisplayChar(ans_node->data_.name[i + prefix_len]);
752 }
753 }
754 else
755 {
756 ans_node = nullptr;
757 LineFeed();
758
759 auto foreach_fun_show = [&](RBTree<const char*>::Node<RamFS::FsNode>& node)
760 {
761 if (strncmp(node->name, prefix_start, prefix_len) == 0)
762 {
763 auto name_len = strlen(node->name);
764 write_stream_ << ConstRawData(node->name, name_len);
765 this->LineFeed();
766 if (ans_node == nullptr)
767 {
768 ans_node = &node;
769 same_char_number = name_len;
770 return ErrorCode::OK;
771 }
772
773 for (size_t i = 0; i < name_len; i++)
774 {
775 if (node->name[i] != ans_node->data_.name[i])
776 {
777 same_char_number = i;
778 break;
779 }
780 }
781
782 if (same_char_number > name_len)
783 {
784 name_len = same_char_number;
785 }
786
787 ans_node = &node;
788 }
789
790 return ErrorCode::OK;
791 };
792
793 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_show);
794
795 ShowHeader();
797
798 for (size_t i = 0; i < same_char_number - prefix_len; i++)
799 {
800 DisplayChar(ans_node->data_.name[i + prefix_len]);
801 }
802 }
803 }
804
811 {
812 if (data != '\r' && data != '\n')
813 {
814 linefeed_flag_ = false;
815 }
816
817 switch (data)
818 {
819 case '\n':
820 case '\r':
821 if (linefeed_flag_)
822 {
823 linefeed_flag_ = false;
824 return;
825 }
826 if (history_index_ >= 0)
827 {
829 }
830 LineFeed();
831 if (input_line_.Size() > 0)
832 {
834 arg_number_ = 0;
835 }
836 ShowHeader();
838 input_line_[0] = '\0';
839 offset_ = 0;
840 break;
841 case 0x7f:
842 case '\b':
843 DeleteChar();
844 break;
845 case '\t':
846 AutoComplete();
847 break;
848 case '\033':
849 flag_ansi_ = 1;
850 break;
851 default:
852 break;
853 }
854 }
855
861 void HandleCharacter(char data)
862 {
863 if (flag_ansi_)
864 {
866 }
867 else if (isprint(data))
868 {
869 DisplayChar(data);
870 }
871 else
872 {
874 }
875 }
876
893 static void ThreadFun(Terminal* term)
894 {
895 Semaphore read_sem, write_sem;
896 ReadOperation op(read_sem);
897
898 term->write_op_ = WriteOperation(write_sem, 10);
899
900 while (true)
901 {
902 term->request_read_size_ = LibXR::min(term->read_port_->Size(), READ_BUFF_SIZE);
903 auto buffer = RawData(term->read_buff_, term->request_read_size_);
904
905 if ((*term->read_port_)(buffer, op) == ErrorCode::OK &&
906 term->request_read_size_ > 0)
907 {
908 term->write_mutex_->Lock();
909 term->Parse(buffer);
910 term->write_stream_.Commit();
911 term->write_mutex_->Unlock();
912 }
913 }
914 }
915
931 static void TaskFun(Terminal* term)
932 {
933 ReadOperation op(term->read_status_);
934
935 auto start_read = [&]()
936 {
937 term->request_read_size_ =
938 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
939 auto buffer = RawData(term->read_buff_, term->request_read_size_);
940 (*term->read_port_)(buffer, op);
941 };
942
943 while (true)
944 {
945 switch (term->read_status_)
946 {
947 case ReadOperation::OperationPollingStatus::READY:
948 {
949 term->request_read_size_ =
950 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
951 auto buffer = RawData(term->read_buff_, term->request_read_size_);
952 (*term->read_port_)(buffer, op);
953 continue;
954 }
955 case ReadOperation::OperationPollingStatus::RUNNING:
956 return;
957 case ReadOperation::OperationPollingStatus::DONE:
958 {
959 term->write_mutex_->Lock();
960 auto buffer = RawData(term->read_buff_, term->request_read_size_);
961 term->Parse(buffer);
962 term->write_stream_.Commit();
963 term->write_mutex_->Unlock();
964 start_read();
965 return;
966 }
967 case ReadOperation::OperationPollingStatus::ERROR:
968 {
969 start_read();
970 return;
971 }
972 }
973 }
974 }
975};
976} // 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:32
基于 BaseQueue 的泛型队列模板类 (Generic queue template class based on BaseQueue).
Definition queue.hpp:180
红黑树的泛型数据节点,继承自 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:272
size_t Size()
获取当前队列的已使用大小。 Gets the currently used size of the queue.
Definition libxr_rw.cpp:24
static LibXR::Mutex * write_mutex_
Write port mutex. 写入端口互斥锁。
Definition libxr_rw.hpp:625
static ReadPort * read_
Read port instance. 读取端口。
Definition libxr_rw.hpp:623
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:624
信号量类,实现线程同步机制 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:190
RamFS::Dir * Path2Dir(char *path)
将路径字符串解析为目录对象 Converts a path string into a directory object
Definition terminal.hpp:415
char * arg_tab_[MAX_ARG_NUMBER]
命令参数列表 Command argument list
Definition terminal.hpp:148
void HandleAnsiCharacter(char data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:595
Queue< LibXR::String< MAX_LINE_SIZE > > history_
历史命令 History of commands
Definition terminal.hpp:150
WritePort * write_port_
写入端口 Write port
Definition terminal.hpp:135
void UpdateDisplayPosition()
更新光标位置 Updates cursor position
Definition terminal.hpp:178
static constexpr char KEY_LEFT[]
左箭头键 Left arrow key
Definition terminal.hpp:40
size_t arg_number_
参数数量 Number of arguments
Definition terminal.hpp:149
uint8_t flag_ansi_
ANSI 控制字符状态 ANSI control character state.
Definition terminal.hpp:145
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:663
void HandleCharacter(char data)
处理输入字符,根据类型调用相应的处理函数 Handles input characters, dispatching them to the appropriate handler
Definition terminal.hpp:861
void HandleControlCharacter(char data)
处理控制字符,包括换行、删除、制表符等 Handles control characters such as newline, delete, and tab
Definition terminal.hpp:810
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:197
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:151
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:146
void ClearLine()
清除当前行 Clears the current line
Definition terminal.hpp:326
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:359
void AddHistory()
将当前输入行添加到历史记录 Adds the current input line to the history
Definition terminal.hpp:374
void DisplayChar(char data)
在终端上显示字符,并根据历史记录模式进行相应操作 Displays a character on the terminal and updates accordingly if history mode...
Definition terminal.hpp:223
RamFS::File * Path2File(char *path)
将路径字符串解析为文件对象 Converts a path string into a file object
Definition terminal.hpp:465
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:338
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:158
void Clear()
清除整个终端屏幕 Clears the entire terminal screen
Definition terminal.hpp:332
void RemoveCharFromInputLine()
从输入行中删除字符,支持在光标位置删除 Removes a character from the input line, supports deletion at the cursor position
Definition terminal.hpp:256
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:931
void GetArgs()
解析输入行,将其拆分为参数数组 Parses the input line and splits it into argument array
Definition terminal.hpp:389
void Parse(RawData &raw_data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:580
void ShowHeader()
显示终端提示符,包括当前目录信息 Displays the terminal prompt, including the current directory information
Definition terminal.hpp:307
RamFS::Dir * current_dir_
当前目录 Current directory
Definition terminal.hpp:144
Stack< char > input_line_
输入行缓冲区 Input line buffer
Definition terminal.hpp:147
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:893
void ExecuteCommand()
解析并执行输入的命令 Parses and executes the entered command
Definition terminal.hpp:501
void DeleteChar()
处理删除字符操作,支持回退删除,并在历史模式下更新显示 Handles the delete character operation, supports backspace deletion,...
Definition terminal.hpp:274
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:152
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:204
WritePort 的流式写入操作器,支持链式 << 操作和批量提交。
Definition libxr_rw.hpp:438
ErrorCode Commit()
手动提交已写入的数据到队列,并尝试续锁。
Definition libxr_rw.cpp:353
WritePort class for handling write operations.
Definition libxr_rw.hpp:413
LibXR 命名空间
Definition ch32_can.hpp:14
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
计算两个数的最小值
Operation< ErrorCode > WriteOperation
Write operation type.
Definition libxr_rw.hpp:241