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_port_(read_port),
98 write_port_(write_port),
100 ramfs_(ramfs),
101 current_dir_(current_dir ? current_dir : &ramfs_.root_),
102 input_line_(MAX_LINE_SIZE + 1),
103 history_(MAX_HISTORY_NUMBER)
104 {
105 ASSERT(read_port != nullptr);
106 ASSERT(write_port != nullptr);
107 ASSERT(read_port->Readable());
108 ASSERT(write_port->Writable());
109
110 if (write_port == STDIO::write_)
111 {
112 if (STDIO::write_mutex_ == nullptr)
113 {
115 }
116
118 STDIO::write_stream_ = &write_stream_;
119 }
120 else
121 {
123 }
124 }
125
128
129 const Mode MODE;
134
136
138 char read_buff_[READ_BUFF_SIZE];
139
141 uint8_t flag_ansi_ = 0;
142 int offset_ = 0;
144 char *arg_tab_[MAX_ARG_NUMBER];
145 size_t arg_number_ = 0;
147 int history_index_ = -1;
148 bool linefeed_flag_ = false;
149
154 void LineFeed()
155 {
156 if (MODE == Mode::CRLF)
157 {
158 write_stream_ << ConstRawData("\r\n");
159 }
160 else if (MODE == Mode::LF)
161 {
163 }
164 else if (MODE == Mode::CR)
165 {
167 }
168 }
169
180
186 bool CanDisplayChar() { return input_line_.EmptySize() > 1; }
187
193 bool CanDeleteChar() { return input_line_.Size() + offset_ > 0; }
194
200 void AddCharToInputLine(char data)
201 {
202 if (offset_ == 0)
203 {
204 input_line_.Push(data);
205 }
206 else
207 {
209 }
210 input_line_[input_line_.Size()] = '\0';
211 }
212
219 void DisplayChar(char data)
220 {
221 bool use_history = false;
222
223 if (history_index_ >= 0)
224 {
226 use_history = true;
227 }
228
229 if (CanDisplayChar())
230 {
231 AddCharToInputLine(data);
232 if (use_history)
233 {
234 ShowHistory();
235 }
236 else
237 {
239 }
240 if (offset_ != 0)
241 {
243 }
244 }
245 }
246
253 {
254 if (offset_ == 0)
255 {
257 }
258 else
259 {
261 }
262 input_line_[input_line_.Size()] = '\0';
263 }
264
271 {
272 bool use_history = false;
273
274 if (history_index_ >= 0)
275 {
277 use_history = true;
278 }
279
280 if (CanDeleteChar())
281 {
283 if (use_history)
284 {
285 ShowHistory();
286 }
287 else
288 {
290 }
291
292 if (offset_ != 0)
293 {
295 }
296 }
297 }
298
304 {
305 write_stream_ << ConstRawData(ramfs_.root_->name, strlen(ramfs_.root_->name));
306 if (current_dir_ == &ramfs_.root_)
307 {
309 }
310 else
311 {
313 }
314
316 }
317
323
329
335 {
336 ClearLine();
337 ShowHeader();
338 offset_ = 0;
339 if (history_index_ >= 0)
340 {
342 history_[-history_index_ - 1].Length());
343 }
344 else
345 {
347 }
348 }
349
356 {
358 for (size_t i = 0; i < history_[-history_index_ - 1].Length(); i++)
359 {
361 }
362 history_index_ = -1;
363 offset_ = 0;
364 }
365
371 {
372 input_line_.Push('\0');
373
374 if (history_.EmptySize() == 0)
375 {
376 history_.Pop();
377 }
378 history_.Push(*reinterpret_cast<String<MAX_LINE_SIZE> *>(&input_line_[0]));
379 }
380
385 void GetArgs()
386 {
387 for (int i = 0; input_line_[i] != '\0'; i++)
388 {
389 if (input_line_[i] == ' ')
390 {
391 input_line_[i] = '\0';
392 }
393 else if (i == 0 || input_line_[i - 1] == '\0')
394 {
395 if (arg_number_ >= MAX_ARG_NUMBER)
396 {
397 return;
398 }
400 }
401 }
402 }
403
411 RamFS::Dir *Path2Dir(char *path)
412 {
413 size_t index = 0;
415
416 if (*path == '/')
417 {
418 index++;
419 dir = &ramfs_.root_;
420 }
421
422 for (size_t i = 0; i < MAX_LINE_SIZE; i++)
423 {
424 auto tmp = strchr(path + index, '/');
425 if (tmp == nullptr)
426 {
427 return dir->FindDir(path + index);
428 }
429 else if (tmp == path + index)
430 {
431 return nullptr;
432 }
433 else
434 {
435 tmp[0] = '\0';
436 dir = dir->FindDir(path + index);
437 tmp[0] = '/';
438 index += tmp - path + 1;
439 if (path[index] == '\0' || dir == nullptr)
440 {
441 return dir;
442 }
443 }
444 }
445
446 return nullptr;
447 }
448
457 {
458 auto name = StrchrRev(path, '/');
459
460 if (name == nullptr)
461 {
462 return current_dir_->FindFile(path);
463 }
464
465 if (name[1] == '\0')
466 {
467 return nullptr;
468 }
469
470 *name = '\0';
471 RamFS::Dir *dir = Path2Dir(path);
472 *name = '/';
473 if (dir != nullptr)
474 {
475 return dir->FindFile(name + 1);
476 }
477 else
478 {
479 return nullptr;
480 }
481 }
482
488 {
489 AddHistory();
490
491 GetArgs();
492
493 if (arg_number_ < 1 || arg_number_ > MAX_ARG_NUMBER)
494 {
495 return;
496 }
497
498 if (strcmp(arg_tab_[0], "cd") == 0)
499 {
500 RamFS::Dir *dir = Path2Dir(arg_tab_[1]);
501 if (dir != nullptr)
502 {
503 current_dir_ = dir;
504 }
505 LineFeed();
506 return;
507 }
508
509 if (strcmp(arg_tab_[0], "ls") == 0)
510 {
511 auto ls_fun = [&](RBTree<const char *>::Node<RamFS::FsNode> &item)
512 {
513 switch (item->type)
514 {
517 break;
520 break;
523 break;
526 break;
527 default:
529 break;
530 }
531 write_stream_ << ConstRawData(item.data_.name);
532 this->LineFeed();
533 return ErrorCode::OK;
534 };
535
536 current_dir_->data_.rbt.Foreach<RamFS::FsNode>(ls_fun);
537 return;
538 }
539
540 auto ans = Path2File(arg_tab_[0]);
541 if (ans == nullptr)
542 {
543 write_stream_ << ConstRawData("Command not found.");
544 LineFeed();
545 return;
546 }
547
548 if ((*ans)->type != RamFS::FileType::EXEC)
549 {
550 write_stream_ << ConstRawData("Not an executable file.");
551 LineFeed();
552 return;
553 }
554
556 (*ans)->Run(arg_number_, arg_tab_);
558 }
559
566 void Parse(RawData &raw_data)
567 {
568 char *buff = static_cast<char *>(raw_data.addr_);
569 for (size_t i = 0; i < raw_data.size_; i++)
570 {
571 HandleCharacter(buff[i]);
572 }
573 }
574
581 void HandleAnsiCharacter(char data)
582 {
583 if (flag_ansi_ == 1)
584 {
585 if (isprint(data))
586 {
587 flag_ansi_++;
588 }
589 else
590 {
591 flag_ansi_ = 0;
592 }
593 }
594 else if (flag_ansi_ == 2)
595 {
596 switch (data)
597 {
598 case 'A':
599 if (history_index_ < int(history_.Size()) - 1)
600 {
602 ShowHistory();
603 }
604 break;
605 case 'B':
606 if (history_index_ >= 0)
607 {
609 ShowHistory();
610 }
611 break;
612 case 'C':
613 if (history_index_ >= 0)
614 {
616 ShowHistory();
617 }
618 if (offset_ < 0)
619 {
620 offset_++;
622 }
623
624 break;
625 case 'D':
626 if (history_index_ >= 0)
627 {
629 ShowHistory();
630 }
631 if (offset_ + input_line_.Size() > 0)
632 {
633 offset_--;
635 }
636 break;
637 default:
638 break;
639 }
640
641 flag_ansi_ = 0;
642 }
643 }
644
650 {
651 /* skip space */
652 char *path = &input_line_[0];
653 while (*path == ' ')
654 {
655 path++;
656 }
657
658 /* find last '/' in first argument */
659 char *tmp = path, *path_end = path;
660
661 while (*tmp != ' ' && *tmp != '\0')
662 {
663 if (*tmp == '/')
664 {
665 path_end = tmp;
666 }
667 tmp++;
668 }
669
670 /* return if not need complete */
671 if (tmp - &input_line_[0] != static_cast<int>(input_line_.Size() + offset_))
672 {
673 return;
674 }
675
676 /* get start of prefix */
677 char *prefix_start = nullptr;
678 RamFS::Dir *dir = nullptr;
679
680 if (path_end == path)
681 {
682 dir = current_dir_;
683 prefix_start = path_end;
684 }
685 else
686 {
687 prefix_start = path_end + 1;
688 }
689
690 /* find dir*/
691 if (dir == nullptr)
692 {
693 *path_end = '\0';
694 dir = Path2Dir(path);
695 *path_end = '/';
696 if (dir == nullptr)
697 {
698 return;
699 }
700 }
701
702 /* prepre for match */
703 RBTree<const char *>::Node<RamFS::FsNode> *ans_node = nullptr;
704 uint32_t number = 0;
705 size_t same_char_number = 0;
706
707 if (*prefix_start == '/')
708 {
709 prefix_start++;
710 }
711
712 int prefix_len = static_cast<int>(tmp - prefix_start);
713
714 auto foreach_fun_find = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
715 {
716 if (strncmp(node->name, prefix_start, prefix_len) == 0)
717 {
718 ans_node = &node;
719 number++;
720 }
721
722 return ErrorCode::OK;
723 };
724
725 /* start match */
726 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_find);
727
728 if (number == 0)
729 {
730 return;
731 }
732 else if (number == 1)
733 {
734 auto name_len = strlen(ans_node->data_.name);
735 for (size_t i = 0; i < name_len - prefix_len; i++)
736 {
737 DisplayChar(ans_node->data_.name[i + prefix_len]);
738 }
739 }
740 else
741 {
742 ans_node = nullptr;
743 LineFeed();
744
745 auto foreach_fun_show = [&](RBTree<const char *>::Node<RamFS::FsNode> &node)
746 {
747 if (strncmp(node->name, prefix_start, prefix_len) == 0)
748 {
749 auto name_len = strlen(node->name);
750 write_stream_ << ConstRawData(node->name, name_len);
751 this->LineFeed();
752 if (ans_node == nullptr)
753 {
754 ans_node = &node;
755 same_char_number = name_len;
756 return ErrorCode::OK;
757 }
758
759 for (size_t i = 0; i < name_len; i++)
760 {
761 if (node->name[i] != ans_node->data_.name[i])
762 {
763 same_char_number = i;
764 break;
765 }
766 }
767
768 if (same_char_number > name_len)
769 {
770 name_len = same_char_number;
771 }
772
773 ans_node = &node;
774 }
775
776 return ErrorCode::OK;
777 };
778
779 (*dir)->rbt.Foreach<RamFS::FsNode>(foreach_fun_show);
780
781 ShowHeader();
783
784 for (size_t i = 0; i < same_char_number - prefix_len; i++)
785 {
786 DisplayChar(ans_node->data_.name[i + prefix_len]);
787 }
788 }
789 }
790
797 {
798 if (data != '\r' && data != '\n')
799 {
800 linefeed_flag_ = false;
801 }
802
803 switch (data)
804 {
805 case '\n':
806 case '\r':
807 if (linefeed_flag_)
808 {
809 linefeed_flag_ = false;
810 return;
811 }
812 if (history_index_ >= 0)
813 {
815 }
816 LineFeed();
817 if (input_line_.Size() > 0)
818 {
820 arg_number_ = 0;
821 }
822 ShowHeader();
824 input_line_[0] = '\0';
825 offset_ = 0;
826 break;
827 case 0x7f:
828 case '\b':
829 DeleteChar();
830 break;
831 case '\t':
832 AutoComplete();
833 break;
834 case '\033':
835 flag_ansi_ = 1;
836 break;
837 default:
838 break;
839 }
840 }
841
847 void HandleCharacter(char data)
848 {
849 if (flag_ansi_)
850 {
852 }
853 else if (isprint(data))
854 {
855 DisplayChar(data);
856 }
857 else
858 {
860 }
861 }
862
879 static void ThreadFun(Terminal *term)
880 {
881 RawData buff = term->read_buff_;
882
883 Semaphore read_sem, write_sem;
884 ReadOperation op(read_sem);
885
886 term->write_op_.type = WriteOperation::OperationType::NONE;
887 term->write_op_.data.sem_info.sem = &write_sem;
888 term->write_op_.data.sem_info.timeout = 10;
889 term->write_op_.type = WriteOperation::OperationType::BLOCK;
890
891 while (true)
892 {
893 buff.size_ = LibXR::min(term->read_port_->Size(), READ_BUFF_SIZE);
894 if ((*term->read_port_)(buff, op) == ErrorCode::OK)
895 {
896 if (term->read_port_->read_size_ > 0)
897 {
898 buff.size_ = term->read_port_->read_size_;
899 term->write_mutex_->Lock();
900 term->Parse(buff);
901 term->write_stream_.Commit();
902 term->write_mutex_->Unlock();
903 }
904 }
905 }
906 }
907
923 static void TaskFun(Terminal *term)
924 {
925 RawData buff = term->read_buff_;
926 buff.size_ = LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
927
928 ReadOperation op(term->read_status_);
929
930 while (true)
931 {
932 switch (term->read_status_)
933 {
934 case ReadOperation::OperationPollingStatus::READY:
935 buff.size_ =
936 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
937 (*term->read_port_)(buff, op);
938 continue;
939 case ReadOperation::OperationPollingStatus::RUNNING:
940 return;
941 case ReadOperation::OperationPollingStatus::DONE:
942 buff.size_ = term->read_port_->read_size_;
943 if (buff.size_ > 0)
944 {
945 term->write_mutex_->Lock();
946 term->Parse(buff);
947 term->write_stream_.Commit();
948 term->write_mutex_->Unlock();
949 }
950 buff.size_ =
951 LibXR::min(LibXR::max(1u, term->read_port_->Size()), READ_BUFF_SIZE);
952 (*term->read_port_)(buff, op);
953 return;
954 }
955 }
956 }
957};
958} // 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::@4 data
OperationType type
Definition libxr_rw.hpp:225
基于 BaseQueue 的泛型队列模板类 (Generic queue template class based on BaseQueue).
Definition queue.hpp:171
红黑树的泛型数据节点,继承自 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:81
文件系统节点基类,所有文件和目录均继承自该类 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:457
原始数据封装类。 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:268
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:600
static ReadPort * read_
Read port instance. 读取端口。
Definition libxr_rw.hpp:598
static WritePort * write_
Write port instance. 写入端口。
Definition libxr_rw.hpp:599
信号量类,实现线程同步机制 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:186
RamFS::Dir * Path2Dir(char *path)
将路径字符串解析为目录对象 Converts a path string into a directory object
Definition terminal.hpp:411
char * arg_tab_[MAX_ARG_NUMBER]
命令参数列表 Command argument list
Definition terminal.hpp:144
void HandleAnsiCharacter(char data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:581
Queue< LibXR::String< MAX_LINE_SIZE > > history_
历史命令 History of commands
Definition terminal.hpp:146
WritePort * write_port_
写入端口 Write port
Definition terminal.hpp:132
void UpdateDisplayPosition()
更新光标位置 Updates cursor position
Definition terminal.hpp:174
static constexpr char KEY_LEFT[]
左箭头键 Left arrow key
Definition terminal.hpp:40
size_t arg_number_
参数数量 Number of arguments
Definition terminal.hpp:145
uint8_t flag_ansi_
ANSI 控制字符状态 ANSI control character state.
Definition terminal.hpp:141
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:649
void HandleCharacter(char data)
处理输入字符,根据类型调用相应的处理函数 Handles input characters, dispatching them to the appropriate handler
Definition terminal.hpp:847
void HandleControlCharacter(char data)
处理控制字符,包括换行、删除、制表符等 Handles control characters such as newline, delete, and tab
Definition terminal.hpp:796
ReadPort * read_port_
读取端口 Read port
Definition terminal.hpp:131
WriteOperation write_op_
终端写操作 Terminal write operation
Definition terminal.hpp:130
bool CanDeleteChar()
检查是否可以删除字符 Checks if a character can be deleted
Definition terminal.hpp:193
static constexpr char KEY_LOAD[]
恢复光标位置 Restore cursor position
Definition terminal.hpp:42
char read_buff_[READ_BUFF_SIZE]
读取缓冲区 Read buffer
Definition terminal.hpp:138
int history_index_
当前历史索引 Current history index
Definition terminal.hpp:147
RamFS & ramfs_
关联的文件系统 Associated file system
Definition terminal.hpp:137
WritePort::Stream write_stream_
写入流 Write stream
Definition terminal.hpp:133
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:142
void ClearLine()
清除当前行 Clears the current line
Definition terminal.hpp:322
LibXR::Mutex * write_mutex_
写入端口互斥锁 Write port mutex
Definition terminal.hpp:135
void CopyHistoryToInputLine()
将历史命令复制到输入行,并重置历史索引和光标偏移 Copies the history command to the input line and resets history index and cu...
Definition terminal.hpp:355
void AddHistory()
将当前输入行添加到历史记录 Adds the current input line to the history
Definition terminal.hpp:370
void DisplayChar(char data)
在终端上显示字符,并根据历史记录模式进行相应操作 Displays a character on the terminal and updates accordingly if history mode...
Definition terminal.hpp:219
RamFS::File * Path2File(char *path)
将路径字符串解析为文件对象 Converts a path string into a file object
Definition terminal.hpp:456
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:334
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:154
void Clear()
清除整个终端屏幕 Clears the entire terminal screen
Definition terminal.hpp:328
void RemoveCharFromInputLine()
从输入行中删除字符,支持在光标位置删除 Removes a character from the input line, supports deletion at the cursor position
Definition terminal.hpp:252
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:923
void GetArgs()
解析输入行,将其拆分为参数数组 Parses the input line and splits it into argument array
Definition terminal.hpp:385
void Parse(RawData &raw_data)
解析输入数据流,将其转换为字符并处理 Parses the input data stream, converting it into characters and processing them
Definition terminal.hpp:566
void ShowHeader()
显示终端提示符,包括当前目录信息 Displays the terminal prompt, including the current directory information
Definition terminal.hpp:303
RamFS::Dir * current_dir_
当前目录 Current directory
Definition terminal.hpp:140
Stack< char > input_line_
输入行缓冲区 Input line buffer
Definition terminal.hpp:143
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:879
void ExecuteCommand()
解析并执行输入的命令 Parses and executes the entered command
Definition terminal.hpp:487
void DeleteChar()
处理删除字符操作,支持回退删除,并在历史模式下更新显示 Handles the delete character operation, supports backspace deletion,...
Definition terminal.hpp:270
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:148
const Mode MODE
终端换行模式 Terminal line feed mode
Definition terminal.hpp:129
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:200
WritePort 的流式写入操作器,支持链式 << 操作和批量提交。
Definition libxr_rw.hpp:428
ErrorCode Commit()
手动提交已写入的数据到队列,并尝试续锁。
Definition libxr_rw.cpp:402
WritePort class for handling write operations.
Definition libxr_rw.hpp:402
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
计算两个数的最小值